Document handling via REST
This commit is contained in:
parent
a1f2c8cd12
commit
49a3fa99e1
|
|
@ -20,7 +20,7 @@ const documents = {
|
|||
"\n query assignmentCompletionQuery(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n ) {\n assignment(id: $assignmentId) {\n assignment_type\n needs_expert_evaluation\n max_points\n content_type\n effort_required\n evaluation_description\n evaluation_document_url\n evaluation_tasks\n id\n intro_text\n performance_objectives\n slug\n tasks\n title\n translation_key\n competence_certificate {\n ...CoursePageFields\n }\n }\n assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n assignment_user_id: $assignmentUserId\n learning_content_page_id: $learningContentId\n ) {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_user {\n id\n }\n assignment_user {\n id\n }\n evaluation_points\n evaluation_max_points\n evaluation_passed\n edoniq_extended_time_flag\n completion_data\n }\n }\n": types.AssignmentCompletionQueryDocument,
|
||||
"\n query courseQuery($courseId: ID!) {\n course(id: $courseId) {\n id\n slug\n title\n category_name\n learning_path {\n id\n }\n }\n }\n": types.CourseQueryDocument,
|
||||
"\n query competenceCertificateQuery($courseSlug: String!, $courseSessionId: ID!) {\n competence_certificate_list(course_slug: $courseSlug) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n completion(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n title\n id\n slug\n content_type\n frontend_url\n circle {\n ...CoursePageFields\n }\n }\n }\n }\n }\n }\n": types.CompetenceCertificateQueryDocument,
|
||||
"\n query courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n }\n users {\n id\n user_id\n first_name\n last_name\n email\n avatar_url\n role\n circles {\n id\n title\n slug\n }\n }\n attendance_courses {\n id\n location\n trainer\n due_date {\n id\n start\n end\n }\n learning_content_id\n learning_content {\n id\n title\n circle {\n id\n title\n slug\n }\n }\n }\n assignments {\n id\n submission_deadline {\n id\n start\n }\n evaluation_deadline {\n id\n start\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n edoniq_tests {\n id\n deadline {\n id\n start\n end\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n documents {\n id\n name\n file_name\n url\n learning_sequence {\n id\n title\n circle {\n id\n slug\n title\n }\n }\n }\n }\n }\n": types.CourseSessionDetailDocument,
|
||||
"\n query courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n }\n users {\n id\n user_id\n first_name\n last_name\n email\n avatar_url\n role\n circles {\n id\n title\n slug\n }\n }\n attendance_courses {\n id\n location\n trainer\n due_date {\n id\n start\n end\n }\n learning_content_id\n learning_content {\n id\n title\n circle {\n id\n title\n slug\n }\n }\n }\n assignments {\n id\n submission_deadline {\n id\n start\n }\n evaluation_deadline {\n id\n start\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n edoniq_tests {\n id\n deadline {\n id\n start\n end\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n }\n }\n": types.CourseSessionDetailDocument,
|
||||
"\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $data: GenericScalar!\n $submitted: Boolean\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n data: $data\n submitted: $submitted\n ) {\n feedback_response {\n id\n data\n submitted\n }\n errors {\n field\n messages\n }\n }\n }\n": types.SendFeedbackMutationDocument,
|
||||
};
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ export function graphql(source: "\n query competenceCertificateQuery($courseSlu
|
|||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n query courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n }\n users {\n id\n user_id\n first_name\n last_name\n email\n avatar_url\n role\n circles {\n id\n title\n slug\n }\n }\n attendance_courses {\n id\n location\n trainer\n due_date {\n id\n start\n end\n }\n learning_content_id\n learning_content {\n id\n title\n circle {\n id\n title\n slug\n }\n }\n }\n assignments {\n id\n submission_deadline {\n id\n start\n }\n evaluation_deadline {\n id\n start\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n edoniq_tests {\n id\n deadline {\n id\n start\n end\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n documents {\n id\n name\n file_name\n url\n learning_sequence {\n id\n title\n circle {\n id\n slug\n title\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n }\n users {\n id\n user_id\n first_name\n last_name\n email\n avatar_url\n role\n circles {\n id\n title\n slug\n }\n }\n attendance_courses {\n id\n location\n trainer\n due_date {\n id\n start\n end\n }\n learning_content_id\n learning_content {\n id\n title\n circle {\n id\n title\n slug\n }\n }\n }\n assignments {\n id\n submission_deadline {\n id\n start\n }\n evaluation_deadline {\n id\n start\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n edoniq_tests {\n id\n deadline {\n id\n start\n end\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n documents {\n id\n name\n file_name\n url\n learning_sequence {\n id\n title\n circle {\n id\n slug\n title\n }\n }\n }\n }\n }\n"];
|
||||
export function graphql(source: "\n query courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n }\n users {\n id\n user_id\n first_name\n last_name\n email\n avatar_url\n role\n circles {\n id\n title\n slug\n }\n }\n attendance_courses {\n id\n location\n trainer\n due_date {\n id\n start\n end\n }\n learning_content_id\n learning_content {\n id\n title\n circle {\n id\n title\n slug\n }\n }\n }\n assignments {\n id\n submission_deadline {\n id\n start\n }\n evaluation_deadline {\n id\n start\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n edoniq_tests {\n id\n deadline {\n id\n start\n end\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n }\n users {\n id\n user_id\n first_name\n last_name\n email\n avatar_url\n role\n circles {\n id\n title\n slug\n }\n }\n attendance_courses {\n id\n location\n trainer\n due_date {\n id\n start\n end\n }\n learning_content_id\n learning_content {\n id\n title\n circle {\n id\n title\n slug\n }\n }\n }\n assignments {\n id\n submission_deadline {\n id\n start\n }\n evaluation_deadline {\n id\n start\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n edoniq_tests {\n id\n deadline {\n id\n start\n end\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -204,21 +204,6 @@ export const COURSE_SESSION_DETAIL_QUERY = graphql(`
|
|||
}
|
||||
}
|
||||
}
|
||||
documents {
|
||||
id
|
||||
name
|
||||
file_name
|
||||
url
|
||||
learning_sequence {
|
||||
id
|
||||
title
|
||||
circle {
|
||||
id
|
||||
slug
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import * as log from "loglevel";
|
||||
import { onMounted } from "vue";
|
||||
import { useCourseSessionDetailQuery } from "@/composables";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
}>();
|
||||
|
||||
onMounted(async () => {
|
||||
log.debug("TestCourseSessionComposablePage mounted");
|
||||
});
|
||||
|
||||
// const courseSession = useCurrentCourseSession();
|
||||
const queryResult = useCourseSessionDetailQuery("-1");
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>Hello World</h1>
|
||||
|
||||
<pre>{{ queryResult.courseSessionDetail }}</pre>
|
||||
</template>
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
<script setup lang="ts">
|
||||
import { useCockpitStore } from "@/stores/cockpit";
|
||||
import { useCompetenceStore } from "@/stores/competence";
|
||||
import { useLearningPathStore } from "@/stores/learningPath";
|
||||
import * as log from "loglevel";
|
||||
|
|
@ -16,7 +15,6 @@ const props = defineProps<{
|
|||
|
||||
log.debug("CockpitUserProfilePage created", props.userId);
|
||||
|
||||
const cockpitStore = useCockpitStore();
|
||||
const competenceStore = useCompetenceStore();
|
||||
const learningPathStore = useLearningPathStore();
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ const submittables = computed(() => {
|
|||
return [];
|
||||
}
|
||||
return learningPath.circles
|
||||
.filter((circle) => props.selectedCircle == circle.id)
|
||||
.filter((circle) => props.selectedCircle.toString() == circle.id.toString())
|
||||
.flatMap((circle) => {
|
||||
const learningContents = circle.flatLearningContents.filter(
|
||||
(lc) =>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { useCourseSessionDetailQuery, useCurrentCourseSession } from "@/composables";
|
||||
import { useCurrentCourseSession } from "@/composables";
|
||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||
import { useCockpitStore } from "@/stores/cockpit";
|
||||
import ItModal from "@/components/ui/ItModal.vue";
|
||||
|
|
@ -9,7 +9,11 @@ import { useTranslation } from "i18next-vue";
|
|||
import type { CircleDocument, DocumentUploadData } from "@/types";
|
||||
import dialog from "@/utils/confirm-dialog";
|
||||
import log from "loglevel";
|
||||
import { uploadCircleDocument } from "@/services/files";
|
||||
import {
|
||||
deleteCircleDocument,
|
||||
fetchCourseSessionDocuments,
|
||||
uploadCircleDocument,
|
||||
} from "@/services/files";
|
||||
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
||||
import DocumentListItem from "@/components/circle/DocumentListItem.vue";
|
||||
import { useCircleStore } from "@/stores/circle";
|
||||
|
|
@ -19,7 +23,6 @@ const courseSession = useCurrentCourseSession();
|
|||
const circleStore = useCircleStore();
|
||||
|
||||
const courseSessionsStore = useCourseSessionsStore();
|
||||
const courseSessionDetailResults = useCourseSessionDetailQuery();
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
|
@ -27,8 +30,25 @@ const showUploadModal = ref(false);
|
|||
const showUploadErrorMessage = ref(false);
|
||||
const isUploading = ref(false);
|
||||
|
||||
const circleDocumentsResultData = ref<CircleDocument[]>([]);
|
||||
let courseSessionDocumentsUrl = "";
|
||||
|
||||
async function fetchDocuments() {
|
||||
const result = await fetchCourseSessionDocuments(courseSession.value?.id);
|
||||
if (result.length > 0) {
|
||||
circleDocumentsResultData.value = result;
|
||||
} else {
|
||||
circleDocumentsResultData.value = [];
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
log.debug("DocumentPage mounted");
|
||||
if (courseSession.value?.id) {
|
||||
courseSessionDocumentsUrl = `/api/core/document/list/${courseSession.value?.id}/`;
|
||||
}
|
||||
|
||||
await fetchDocuments();
|
||||
});
|
||||
|
||||
watch(
|
||||
|
|
@ -48,14 +68,12 @@ watch(
|
|||
const dropdownLearningSequences = computed(() =>
|
||||
circleStore.circle?.learningSequences.map((sequence) => ({
|
||||
id: sequence.id,
|
||||
name: `${sequence.title} ${sequence.id}`,
|
||||
name: `${sequence.title}`,
|
||||
}))
|
||||
);
|
||||
|
||||
const circleDocuments = computed(() => {
|
||||
const documents =
|
||||
courseSessionDetailResults.courseSessionDetail.value?.documents ?? [];
|
||||
return documents.filter(
|
||||
return circleDocumentsResultData.value.filter(
|
||||
(d) => d.learning_sequence.circle.slug === cockpitStore.currentCircle?.slug
|
||||
);
|
||||
});
|
||||
|
|
@ -67,7 +85,10 @@ const deleteDocument = async (doc: CircleDocument) => {
|
|||
};
|
||||
try {
|
||||
await dialog.confirm(options);
|
||||
courseSessionsStore.removeDocument(doc.id);
|
||||
await deleteCircleDocument(doc.id, courseSessionDocumentsUrl);
|
||||
circleDocumentsResultData.value = circleDocumentsResultData.value.filter(
|
||||
(d) => d.id !== doc.id
|
||||
);
|
||||
} catch (e) {
|
||||
log.debug("rejected");
|
||||
}
|
||||
|
|
@ -81,11 +102,13 @@ async function uploadDocument(data: DocumentUploadData) {
|
|||
if (!courseSessionsStore.currentCourseSession) {
|
||||
throw new Error("No course session found");
|
||||
}
|
||||
const newDocument = await uploadCircleDocument(
|
||||
await uploadCircleDocument(
|
||||
data,
|
||||
courseSessionsStore.currentCourseSession.id
|
||||
courseSessionsStore.currentCourseSession.id,
|
||||
courseSessionDocumentsUrl
|
||||
);
|
||||
courseSessionsStore.addDocument(newDocument);
|
||||
await fetchDocuments();
|
||||
|
||||
showUploadModal.value = false;
|
||||
isUploading.value = false;
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -21,18 +21,33 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import DocumentListItem from "@/components/circle/DocumentListItem.vue";
|
||||
import { useCourseSessionDetailQuery } from "@/composables";
|
||||
import { computed } from "vue";
|
||||
import { useCurrentCourseSession } from "@/composables";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { useCircleStore } from "@/stores/circle";
|
||||
import type { CircleDocument } from "@/types";
|
||||
import { fetchCourseSessionDocuments } from "@/services/files";
|
||||
|
||||
const courseSessionDetailResults = useCourseSessionDetailQuery();
|
||||
const courseSession = useCurrentCourseSession();
|
||||
const circleStore = useCircleStore();
|
||||
|
||||
const circleDocumentsResultData = ref<CircleDocument[]>([]);
|
||||
|
||||
async function fetchDocuments() {
|
||||
const result = await fetchCourseSessionDocuments(courseSession.value?.id);
|
||||
if (result.length > 0) {
|
||||
circleDocumentsResultData.value = result;
|
||||
} else {
|
||||
circleDocumentsResultData.value = [];
|
||||
}
|
||||
}
|
||||
|
||||
const circleDocuments = computed(() => {
|
||||
const documents =
|
||||
courseSessionDetailResults.courseSessionDetail.value?.documents ?? [];
|
||||
return documents.filter(
|
||||
return circleDocumentsResultData.value.filter(
|
||||
(d) => d.learning_sequence.circle.slug === circleStore.circle?.slug
|
||||
);
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
await fetchDocuments();
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -98,11 +98,6 @@ const router = createRouter({
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/course/:courseSlug/test-composable",
|
||||
component: () => import("../pages/TestCourseSessionComposablePage.vue"),
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: "/course/:courseSlug/learn",
|
||||
component: () =>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { itDelete, itFetch, itPost } from "@/fetchHelpers";
|
||||
import { bustItGetCache, itDelete, itFetch, itGetCached, itPost } from "@/fetchHelpers";
|
||||
import { getCookieValue } from "@/router/guards";
|
||||
import type { CircleDocument, DocumentUploadData } from "@/types";
|
||||
import type { DocumentUploadData } from "@/types";
|
||||
|
||||
type FileData = {
|
||||
fields: Record<string, string>;
|
||||
|
|
@ -73,8 +73,9 @@ function handleUpload(url: string, options: RequestInit) {
|
|||
|
||||
export async function uploadCircleDocument(
|
||||
data: DocumentUploadData,
|
||||
courseSessionId: number
|
||||
): Promise<CircleDocument> {
|
||||
courseSessionId: number,
|
||||
bustCacheUrlKey = ""
|
||||
) {
|
||||
if (data.file === null) {
|
||||
throw new Error("No file selected");
|
||||
}
|
||||
|
|
@ -82,22 +83,25 @@ export async function uploadCircleDocument(
|
|||
const startData = await startFileUpload(data, courseSessionId);
|
||||
|
||||
await uploadFile(startData, data.file);
|
||||
const response = await itPost(`/api/core/file/finish/`, {
|
||||
const response = itPost(`/api/core/file/finish/`, {
|
||||
file_id: startData.file_id,
|
||||
});
|
||||
|
||||
const newDocument: CircleDocument = {
|
||||
id: startData.id,
|
||||
name: data.name,
|
||||
file_name: data.file.name,
|
||||
url: response.url,
|
||||
course_session: courseSessionId,
|
||||
learning_sequence: data.learningSequence.id,
|
||||
};
|
||||
if (bustCacheUrlKey) {
|
||||
bustItGetCache(bustCacheUrlKey);
|
||||
}
|
||||
|
||||
return Promise.resolve(newDocument);
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function deleteCircleDocument(documentId: string) {
|
||||
return itDelete(`/api/core/document/${documentId}/`);
|
||||
export async function deleteCircleDocument(documentId: string, bustCacheUrlKey = "") {
|
||||
const result = itDelete(`/api/core/document/${documentId}/`);
|
||||
if (bustCacheUrlKey) {
|
||||
bustItGetCache(bustCacheUrlKey);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function fetchCourseSessionDocuments(courseSessionId: number) {
|
||||
return itGetCached(`/api/core/document/list/${courseSessionId}/`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import type {
|
|||
CompetenceProfilePage,
|
||||
PerformanceCriteria,
|
||||
} from "@/types";
|
||||
import i18next from "i18next";
|
||||
import _ from "lodash";
|
||||
import cloneDeep from "lodash/cloneDeep";
|
||||
import groupBy from "lodash/groupBy";
|
||||
|
|
@ -17,9 +16,6 @@ import { defineStore } from "pinia";
|
|||
|
||||
export type CompetenceStoreState = {
|
||||
competenceProfilePages: Map<string, CompetenceProfilePage>;
|
||||
|
||||
selectedCircle: { id: string; name: string };
|
||||
availableCircles: { id: string; name: string }[];
|
||||
circles: CircleLight[];
|
||||
};
|
||||
|
||||
|
|
@ -28,8 +24,6 @@ export const useCompetenceStore = defineStore({
|
|||
state: () => {
|
||||
return {
|
||||
competenceProfilePages: new Map<string, CompetenceProfilePage>(),
|
||||
selectedCircle: { id: "all", name: `Circle: ${i18next.t("Alle")}` },
|
||||
availableCircles: [],
|
||||
circles: [],
|
||||
} as CompetenceStoreState;
|
||||
},
|
||||
|
|
@ -52,13 +46,7 @@ export const useCompetenceStore = defineStore({
|
|||
};
|
||||
},
|
||||
criteriaByCompetence(competence: CompetencePage) {
|
||||
return competence.children.filter((criteria) => {
|
||||
if (this.selectedCircle.id != "all") {
|
||||
return criteria.circle.translation_key === this.selectedCircle.id;
|
||||
}
|
||||
|
||||
return competence.children;
|
||||
});
|
||||
},
|
||||
competenceProfilePage(userId: string | undefined = undefined) {
|
||||
if (!userId) {
|
||||
|
|
@ -88,14 +76,10 @@ export const useCompetenceStore = defineStore({
|
|||
["asc"]
|
||||
);
|
||||
|
||||
if (this.selectedCircle.id !== "all") {
|
||||
criteria = criteria.filter(
|
||||
(c) => c.circle.translation_key === this.selectedCircle.id
|
||||
);
|
||||
}
|
||||
|
||||
if (circleId) {
|
||||
criteria = criteria.filter((c) => circleId === c.circle.id);
|
||||
criteria = criteria.filter(
|
||||
(c) => circleId.toString() === c.circle.id.toString()
|
||||
);
|
||||
}
|
||||
|
||||
return criteria;
|
||||
|
|
@ -116,12 +100,7 @@ export const useCompetenceStore = defineStore({
|
|||
if (competenceProfilePage?.children.length) {
|
||||
return _.orderBy(
|
||||
competenceProfilePage.children.filter((competence) => {
|
||||
let criteria = competence.children;
|
||||
if (this.selectedCircle.id != "all") {
|
||||
criteria = criteria.filter((criteria) => {
|
||||
return criteria.circle.translation_key === this.selectedCircle.id;
|
||||
});
|
||||
}
|
||||
const criteria = competence.children;
|
||||
return criteria.length > 0;
|
||||
}),
|
||||
["competence_id"],
|
||||
|
|
@ -159,10 +138,6 @@ export const useCompetenceStore = defineStore({
|
|||
this.competenceProfilePages.set(userId, cloneDeep(competenceProfilePage));
|
||||
|
||||
this.circles = competenceProfilePage.circles;
|
||||
const circles = competenceProfilePage.circles.map((c: CircleLight) => {
|
||||
return { id: c.translation_key, name: `Circle: ${c.title}` };
|
||||
});
|
||||
this.availableCircles = [{ id: "all", name: "Circle: Alle" }, ...circles];
|
||||
|
||||
await this.parseCompletionData(userId);
|
||||
|
||||
|
|
|
|||
|
|
@ -146,35 +146,6 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
|
|||
return Boolean(isCourseExpert && (inLearningPath() || inCompetenceProfile()));
|
||||
});
|
||||
|
||||
// const canUploadCircleDocuments = computed(() => {
|
||||
// const userStore = useUserStore();
|
||||
// return (
|
||||
// circleExperts.value.filter((expert) => expert.user_id === userStore.id).length > 0
|
||||
// );
|
||||
// });
|
||||
|
||||
// const circleDocuments = computed(() => {
|
||||
// const circleStore = useCircleStore();
|
||||
//
|
||||
// return (
|
||||
// circleStore.circle?.learningSequences
|
||||
// .map((ls) => ({ id: ls.id, title: ls.title, documents: [] }))
|
||||
// .map((ls: { id: number; title: string; documents: CircleDocument[] }) => {
|
||||
// if (currentCourseSession.value === undefined) {
|
||||
// return ls;
|
||||
// }
|
||||
//
|
||||
// for (const document of currentCourseSession.value.documents) {
|
||||
// if (document.learning_sequence === ls.id) {
|
||||
// ls.documents.push(document);
|
||||
// }
|
||||
// }
|
||||
// return ls;
|
||||
// })
|
||||
// .filter((ls) => ls.documents.length > 0) || []
|
||||
// );
|
||||
// });
|
||||
|
||||
function hasCockpit(courseSession: CourseSession) {
|
||||
const userStore = useUserStore();
|
||||
return (
|
||||
|
|
@ -183,10 +154,6 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
|
|||
);
|
||||
}
|
||||
|
||||
// function addDocument(document: CircleDocument) {
|
||||
// currentCourseSession.value?.documents.push(document);
|
||||
// }
|
||||
|
||||
function allDueDates() {
|
||||
const allDueDatesReturn: DueDate[] = [];
|
||||
|
||||
|
|
@ -211,26 +178,6 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
|
|||
});
|
||||
}
|
||||
|
||||
// async function startUpload() {
|
||||
// log.debug("loadCourseSessionsData called");
|
||||
// allCourseSessions.value = await itPost(`/api/core/file/start`, {
|
||||
// file_type: "image/png",
|
||||
// file_name: "test.png",
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// async function removeDocument(documentId: string) {
|
||||
// await deleteCircleDocument(documentId);
|
||||
//
|
||||
// if (currentCourseSession.value === undefined) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// currentCourseSession.value.documents = currentCourseSession.value?.documents.filter(
|
||||
// (d) => d.id !== documentId
|
||||
// );
|
||||
// }
|
||||
|
||||
return {
|
||||
uniqueCourseSessionsByCourse,
|
||||
allCurrentCourseSessions,
|
||||
|
|
@ -240,9 +187,6 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
|
|||
hasCockpit,
|
||||
hasCourseSessionPreview,
|
||||
currentCourseSessionHasCockpit,
|
||||
// addDocument,
|
||||
// startUpload,
|
||||
// removeDocument,
|
||||
allDueDates,
|
||||
|
||||
// use `useCurrentCourseSession` whenever possible
|
||||
|
|
|
|||
|
|
@ -569,7 +569,6 @@ export interface CourseSessionDetail {
|
|||
assignments: CourseSessionAssignment[];
|
||||
attendance_courses: CourseSessionAttendanceCourse[];
|
||||
edoniq_tests: CourseSessionEdoniqTest[];
|
||||
documents: CircleDocument[];
|
||||
users: CourseSessionUser[];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ from vbv_lernwelt.course.views import (
|
|||
document_direct_upload,
|
||||
document_upload_finish,
|
||||
document_upload_start,
|
||||
get_course_session_users,
|
||||
get_course_sessions,
|
||||
mark_course_completion_view,
|
||||
request_course_completion,
|
||||
request_course_completion_for_user,
|
||||
)
|
||||
from vbv_lernwelt.course_session.views import get_course_session_documents
|
||||
from vbv_lernwelt.edoniq_test.views import (
|
||||
export_students,
|
||||
export_students_and_trainers,
|
||||
|
|
@ -90,6 +90,10 @@ urlpatterns = [
|
|||
path('server/documents/', include(wagtaildocs_urls)),
|
||||
path('server/pages/', include(wagtail_urls)),
|
||||
|
||||
# core
|
||||
re_path(r"server/core/icons/$", generate_web_component_icons,
|
||||
name="generate_web_component_icons"),
|
||||
|
||||
# user management
|
||||
path("sso/", include("vbv_lernwelt.sso.urls")),
|
||||
re_path(r'api/core/me/$', me_user_view, name='me_user_view'),
|
||||
|
|
@ -104,10 +108,6 @@ urlpatterns = [
|
|||
re_path(r"api/notify/email_notification_settings/$", email_notification_settings,
|
||||
name='email_notification_settings'),
|
||||
|
||||
# core
|
||||
re_path(r"server/core/icons/$", generate_web_component_icons,
|
||||
name="generate_web_component_icons"),
|
||||
|
||||
# course
|
||||
path(r"api/course/sessions/", get_course_sessions, name="get_course_sessions"),
|
||||
# path(r"api/course/sessions/<signed_int:course_session_id>/users/",
|
||||
|
|
@ -139,6 +139,9 @@ urlpatterns = [
|
|||
name='file_upload_finish'),
|
||||
path(r"api/core/document/local/<str:file_id>/", document_direct_upload,
|
||||
name='file_upload_local'),
|
||||
path(r'api/core/document/list/<str:course_session_id>/',
|
||||
get_course_session_documents,
|
||||
name='get_course_session_documents'),
|
||||
|
||||
# feedback
|
||||
path(r'api/core/feedback/<str:course_session_id>/summary/',
|
||||
|
|
|
|||
|
|
@ -8,22 +8,22 @@ from graphql import GraphQLError
|
|||
from rest_framework.exceptions import PermissionDenied
|
||||
|
||||
from vbv_lernwelt.course.models import (
|
||||
CircleDocument,
|
||||
Course,
|
||||
CourseBasePage,
|
||||
CoursePage,
|
||||
CourseSession,
|
||||
CourseSessionUser,
|
||||
CircleDocument,
|
||||
)
|
||||
from vbv_lernwelt.course.permissions import has_course_access
|
||||
from vbv_lernwelt.course_session.graphql.types import (
|
||||
CourseSessionAttendanceCourseObjectType,
|
||||
CourseSessionAssignmentObjectType,
|
||||
CourseSessionAttendanceCourseObjectType,
|
||||
CourseSessionEdoniqTestObjectType,
|
||||
)
|
||||
from vbv_lernwelt.course_session.models import (
|
||||
CourseSessionAttendanceCourse,
|
||||
CourseSessionAssignment,
|
||||
CourseSessionAttendanceCourse,
|
||||
CourseSessionEdoniqTest,
|
||||
)
|
||||
from vbv_lernwelt.learnpath.graphql.types import LearningPathObjectType
|
||||
|
|
|
|||
|
|
@ -322,6 +322,9 @@ class CircleDocument(models.Model):
|
|||
"learnpath.LearningSequence", on_delete=models.CASCADE
|
||||
)
|
||||
|
||||
def get_circle(self):
|
||||
return self.learning_sequence.get_circle()
|
||||
|
||||
@property
|
||||
def url(self) -> str:
|
||||
return self.file.url
|
||||
|
|
|
|||
|
|
@ -89,6 +89,8 @@ class CourseSessionSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class CircleDocumentSerializer(serializers.ModelSerializer):
|
||||
learning_sequence = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = CircleDocument
|
||||
fields = [
|
||||
|
|
@ -100,6 +102,20 @@ class CircleDocumentSerializer(serializers.ModelSerializer):
|
|||
"learning_sequence",
|
||||
]
|
||||
|
||||
def get_learning_sequence(self, obj):
|
||||
ls = obj.learning_sequence
|
||||
circle = ls.get_circle()
|
||||
return {
|
||||
"title": ls.title,
|
||||
"id": ls.id,
|
||||
"slug": ls.slug,
|
||||
"circle": {
|
||||
"title": circle.title,
|
||||
"id": circle.id,
|
||||
"slug": circle.slug,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class DocumentUploadStartInputSerializer(serializers.Serializer):
|
||||
file_name = serializers.CharField()
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ from graphene_django import DjangoObjectType
|
|||
|
||||
from vbv_lernwelt.course.permissions import is_course_session_expert
|
||||
from vbv_lernwelt.course_session.models import (
|
||||
CourseSessionAttendanceCourse,
|
||||
CourseSessionAssignment,
|
||||
CourseSessionAttendanceCourse,
|
||||
CourseSessionEdoniqTest,
|
||||
)
|
||||
from vbv_lernwelt.course_session.services.attendance import AttendanceUserStatus
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
from django.shortcuts import render
|
||||
from rest_framework.decorators import api_view
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from rest_framework.response import Response
|
||||
|
||||
# Create your views here.
|
||||
from vbv_lernwelt.course.models import CircleDocument
|
||||
from vbv_lernwelt.course.permissions import has_course_session_access
|
||||
from vbv_lernwelt.course.serializers import CircleDocumentSerializer
|
||||
|
||||
|
||||
@api_view(["GET"])
|
||||
def get_course_session_documents(request, course_session_id):
|
||||
if not has_course_session_access(request.user, course_session_id):
|
||||
raise PermissionDenied()
|
||||
|
||||
circle_documents = CircleDocument.objects.filter(
|
||||
course_session_id=course_session_id
|
||||
)
|
||||
|
||||
return Response(
|
||||
status=200, data=CircleDocumentSerializer(circle_documents, many=True).data
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ from vbv_lernwelt.learnpath.graphql.types import (
|
|||
LearningContentAssignmentObjectType,
|
||||
LearningContentAttendanceCourseObjectType,
|
||||
LearningContentDocumentListObjectType,
|
||||
LearningContentEdoniqTestObjectType,
|
||||
LearningContentFeedbackObjectType,
|
||||
LearningContentLearningModuleObjectType,
|
||||
LearningContentMediaLibraryObjectType,
|
||||
LearningContentPlaceholderObjectType,
|
||||
LearningContentRichTextObjectType,
|
||||
LearningContentEdoniqTestObjectType,
|
||||
LearningContentVideoObjectType,
|
||||
LearningPathObjectType,
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue