diff --git a/client/src/components/dashboard/CompetenceSummary.vue b/client/src/components/dashboard/CompetenceSummary.vue
new file mode 100644
index 00000000..ba701185
--- /dev/null
+++ b/client/src/components/dashboard/CompetenceSummary.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
diff --git a/client/src/components/dashboard/CoursePanel.vue b/client/src/components/dashboard/CoursePanel.vue
new file mode 100644
index 00000000..19cadce3
--- /dev/null
+++ b/client/src/components/dashboard/CoursePanel.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
{{ courseName }}
+
+ {{ widget }}
+
+
+
+
+
+
diff --git a/client/src/gql/gql.ts b/client/src/gql/gql.ts
index eb6023e4..66a37920 100644
--- a/client/src/gql/gql.ts
+++ b/client/src/gql/gql.ts
@@ -23,6 +23,7 @@ const documents = {
"\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\n configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n }\n action_competences {\n competence_id\n ...CoursePageFields\n performance_criteria {\n competence_id\n learning_unit {\n id\n slug\n evaluate_url\n }\n ...CoursePageFields\n }\n }\n learning_path {\n ...CoursePageFields\n topics {\n is_visible\n ...CoursePageFields\n circles {\n description\n goals\n ...CoursePageFields\n learning_sequences {\n icon\n ...CoursePageFields\n learning_units {\n evaluate_url\n ...CoursePageFields\n performance_criteria {\n ...CoursePageFields\n }\n learning_contents {\n can_user_self_toggle_course_completion\n content_url\n minutes\n description\n ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n assignment_type\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n has_extended_time_test\n content_assignment {\n id\n assignment_type\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentRichTextObjectType {\n text\n }\n }\n }\n }\n }\n }\n }\n }\n }\n": types.CourseQueryDocument,
"\n query dashboardConfig {\n dashboard_config {\n id\n slug\n name\n dashboard_type\n course_configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n }\n }\n }\n": types.DashboardConfigDocument,
"\n query dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n competence {\n _id\n total_count\n success_count\n fail_count\n }\n assignment {\n _id\n total_count\n points_max_count\n points_achieved_count\n }\n }\n }\n": types.DashboardProgressDocument,
+ "\n query dashboardCourseData($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n widgets\n }\n }\n": types.DashboardCourseDataDocument,
"\n query courseStatistics($courseId: ID!) {\n course_statistics(course_id: $courseId) {\n _id\n course_id\n course_title\n course_slug\n course_session_properties {\n _id\n sessions {\n id\n name\n }\n generations\n circles {\n id\n name\n }\n }\n course_session_selection_ids\n course_session_selection_metrics {\n _id\n session_count\n participant_count\n expert_count\n }\n attendance_day_presences {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n due_date\n participants_present\n participants_total\n details_url\n }\n summary {\n _id\n days_completed\n participants_present\n }\n }\n feedback_responses {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n experts\n satisfaction_average\n satisfaction_max\n details_url\n }\n summary {\n _id\n satisfaction_average\n satisfaction_max\n total_responses\n }\n }\n assignments {\n _id\n summary {\n _id\n completed_count\n average_passed\n }\n records {\n _id\n course_session_id\n course_session_assignment_id\n circle_id\n generation\n assignment_title\n assignment_type_translation_key\n details_url\n deadline\n metrics {\n _id\n passed_count\n failed_count\n unranked_count\n ranking_completed\n average_passed\n }\n }\n }\n competences {\n _id\n summary {\n _id\n success_total\n fail_total\n }\n records {\n _id\n course_session_id\n generation\n circle_id\n title\n success_count\n fail_count\n details_url\n }\n }\n }\n }\n": types.CourseStatisticsDocument,
"\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $learningContentType: String!\n $data: GenericScalar!\n $submitted: Boolean\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n learning_content_type: $learningContentType\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,
};
@@ -81,6 +82,10 @@ export function graphql(source: "\n query dashboardConfig {\n dashboard_conf
* 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 dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n competence {\n _id\n total_count\n success_count\n fail_count\n }\n assignment {\n _id\n total_count\n points_max_count\n points_achieved_count\n }\n }\n }\n"): (typeof documents)["\n query dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n competence {\n _id\n total_count\n success_count\n fail_count\n }\n assignment {\n _id\n total_count\n points_max_count\n points_achieved_count\n }\n }\n }\n"];
+/**
+ * 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 dashboardCourseData($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n widgets\n }\n }\n"): (typeof documents)["\n query dashboardCourseData($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n widgets\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
diff --git a/client/src/gql/graphql.ts b/client/src/gql/graphql.ts
index e6086ccb..37d161ab 100644
--- a/client/src/gql/graphql.ts
+++ b/client/src/gql/graphql.ts
@@ -361,10 +361,11 @@ export type CoursePageInterface = {
export type CourseProgressType = {
__typename?: 'CourseProgressType';
_id: Scalars['ID']['output'];
- assignment: ProgressDashboardAssignmentType;
- competence: ProgressDashboardCompetenceType;
+ assignment?: Maybe;
+ competence?: Maybe;
course_id: Scalars['ID']['output'];
session_to_continue_id?: Maybe;
+ widgets: Array;
};
export type CourseSessionAssignmentObjectType = {
@@ -907,6 +908,7 @@ export type Query = {
course_session_attendance_course?: Maybe;
course_statistics?: Maybe;
dashboard_config: Array;
+ dashboard_data?: Maybe;
learning_content_assignment?: Maybe;
learning_content_attendance_course?: Maybe;
learning_content_document_list?: Maybe;
@@ -978,6 +980,11 @@ export type QueryCourseStatisticsArgs = {
};
+export type QueryDashboardDataArgs = {
+ course_id: Scalars['ID']['input'];
+};
+
+
export type QueryLearningPathArgs = {
course_id?: InputMaybe;
course_slug?: InputMaybe;
@@ -1046,6 +1053,13 @@ export type UserObjectType = {
username: Scalars['String']['output'];
};
+export type WidgetType =
+ | 'COMPETENCE_CERTIFICATE_WIDGET'
+ | 'COMPETENCE_WIDGET'
+ | 'MENTEE_WIDGET'
+ | 'MENTOR_TASKS_WIDGET'
+ | 'PROGRESS_WIDGET';
+
export type AttendanceCheckMutationMutationVariables = Exact<{
attendanceCourseId: Scalars['ID']['input'];
attendanceUserList: Array> | InputMaybe;
@@ -1278,7 +1292,14 @@ export type DashboardProgressQueryVariables = Exact<{
}>;
-export type DashboardProgressQuery = { __typename?: 'Query', course_progress?: { __typename?: 'CourseProgressType', _id: string, course_id: string, session_to_continue_id?: string | null, competence: { __typename?: 'ProgressDashboardCompetenceType', _id: string, total_count: number, success_count: number, fail_count: number }, assignment: { __typename?: 'ProgressDashboardAssignmentType', _id: string, total_count: number, points_max_count: number, points_achieved_count: number } } | null };
+export type DashboardProgressQuery = { __typename?: 'Query', course_progress?: { __typename?: 'CourseProgressType', _id: string, course_id: string, session_to_continue_id?: string | null, competence?: { __typename?: 'ProgressDashboardCompetenceType', _id: string, total_count: number, success_count: number, fail_count: number } | null, assignment?: { __typename?: 'ProgressDashboardAssignmentType', _id: string, total_count: number, points_max_count: number, points_achieved_count: number } | null } | null };
+
+export type DashboardCourseDataQueryVariables = Exact<{
+ courseId: Scalars['ID']['input'];
+}>;
+
+
+export type DashboardCourseDataQuery = { __typename?: 'Query', course_progress?: { __typename?: 'CourseProgressType', _id: string, course_id: string, session_to_continue_id?: string | null, widgets: Array } | null };
export type CourseStatisticsQueryVariables = Exact<{
courseId: Scalars['ID']['input'];
@@ -1308,5 +1329,6 @@ export const CourseSessionDetailDocument = {"kind":"Document","definitions":[{"k
export const CourseQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"courseQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"slug"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"slug"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"category_name"}},{"kind":"Field","name":{"kind":"Name","value":"configuration"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"enable_circle_documents"}},{"kind":"Field","name":{"kind":"Name","value":"enable_learning_mentor"}},{"kind":"Field","name":{"kind":"Name","value":"enable_competence_certificates"}}]}},{"kind":"Field","name":{"kind":"Name","value":"action_competences"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"performance_criteria"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_id"}},{"kind":"Field","name":{"kind":"Name","value":"learning_unit"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"evaluate_url"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_path"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"topics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"is_visible"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"circles"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"goals"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"learning_sequences"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"learning_units"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evaluate_url"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"performance_criteria"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_contents"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"can_user_self_toggle_course_completion"}},{"kind":"Field","name":{"kind":"Name","value":"content_url"}},{"kind":"Field","name":{"kind":"Name","value":"minutes"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LearningContentAssignmentObjectType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"content_assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LearningContentEdoniqTestObjectType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"checkbox_text"}},{"kind":"Field","name":{"kind":"Name","value":"has_extended_time_test"}},{"kind":"Field","name":{"kind":"Name","value":"content_assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LearningContentRichTextObjectType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"text"}}]}}]}}]}}]}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode;
export const DashboardConfigDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"dashboardConfig"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"dashboard_config"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"dashboard_type"}},{"kind":"Field","name":{"kind":"Name","value":"course_configuration"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"enable_circle_documents"}},{"kind":"Field","name":{"kind":"Name","value":"enable_learning_mentor"}},{"kind":"Field","name":{"kind":"Name","value":"enable_competence_certificates"}}]}}]}}]}}]} as unknown as DocumentNode;
export const DashboardProgressDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"dashboardProgress"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course_progress"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"course_id"}},{"kind":"Field","name":{"kind":"Name","value":"session_to_continue_id"}},{"kind":"Field","name":{"kind":"Name","value":"competence"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"total_count"}},{"kind":"Field","name":{"kind":"Name","value":"success_count"}},{"kind":"Field","name":{"kind":"Name","value":"fail_count"}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"total_count"}},{"kind":"Field","name":{"kind":"Name","value":"points_max_count"}},{"kind":"Field","name":{"kind":"Name","value":"points_achieved_count"}}]}}]}}]}}]} as unknown as DocumentNode;
+export const DashboardCourseDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"dashboardCourseData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course_progress"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"course_id"}},{"kind":"Field","name":{"kind":"Name","value":"session_to_continue_id"}},{"kind":"Field","name":{"kind":"Name","value":"widgets"}}]}}]}}]} as unknown as DocumentNode;
export const CourseStatisticsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"courseStatistics"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course_statistics"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"course_id"}},{"kind":"Field","name":{"kind":"Name","value":"course_title"}},{"kind":"Field","name":{"kind":"Name","value":"course_slug"}},{"kind":"Field","name":{"kind":"Name","value":"course_session_properties"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"sessions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"generations"}},{"kind":"Field","name":{"kind":"Name","value":"circles"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"course_session_selection_ids"}},{"kind":"Field","name":{"kind":"Name","value":"course_session_selection_metrics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"session_count"}},{"kind":"Field","name":{"kind":"Name","value":"participant_count"}},{"kind":"Field","name":{"kind":"Name","value":"expert_count"}}]}},{"kind":"Field","name":{"kind":"Name","value":"attendance_day_presences"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"records"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"course_session_id"}},{"kind":"Field","name":{"kind":"Name","value":"generation"}},{"kind":"Field","name":{"kind":"Name","value":"circle_id"}},{"kind":"Field","name":{"kind":"Name","value":"due_date"}},{"kind":"Field","name":{"kind":"Name","value":"participants_present"}},{"kind":"Field","name":{"kind":"Name","value":"participants_total"}},{"kind":"Field","name":{"kind":"Name","value":"details_url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"summary"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"days_completed"}},{"kind":"Field","name":{"kind":"Name","value":"participants_present"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"feedback_responses"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"records"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"course_session_id"}},{"kind":"Field","name":{"kind":"Name","value":"generation"}},{"kind":"Field","name":{"kind":"Name","value":"circle_id"}},{"kind":"Field","name":{"kind":"Name","value":"experts"}},{"kind":"Field","name":{"kind":"Name","value":"satisfaction_average"}},{"kind":"Field","name":{"kind":"Name","value":"satisfaction_max"}},{"kind":"Field","name":{"kind":"Name","value":"details_url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"summary"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"satisfaction_average"}},{"kind":"Field","name":{"kind":"Name","value":"satisfaction_max"}},{"kind":"Field","name":{"kind":"Name","value":"total_responses"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"summary"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"completed_count"}},{"kind":"Field","name":{"kind":"Name","value":"average_passed"}}]}},{"kind":"Field","name":{"kind":"Name","value":"records"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"course_session_id"}},{"kind":"Field","name":{"kind":"Name","value":"course_session_assignment_id"}},{"kind":"Field","name":{"kind":"Name","value":"circle_id"}},{"kind":"Field","name":{"kind":"Name","value":"generation"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_title"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type_translation_key"}},{"kind":"Field","name":{"kind":"Name","value":"details_url"}},{"kind":"Field","name":{"kind":"Name","value":"deadline"}},{"kind":"Field","name":{"kind":"Name","value":"metrics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"passed_count"}},{"kind":"Field","name":{"kind":"Name","value":"failed_count"}},{"kind":"Field","name":{"kind":"Name","value":"unranked_count"}},{"kind":"Field","name":{"kind":"Name","value":"ranking_completed"}},{"kind":"Field","name":{"kind":"Name","value":"average_passed"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"competences"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"summary"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"success_total"}},{"kind":"Field","name":{"kind":"Name","value":"fail_total"}}]}},{"kind":"Field","name":{"kind":"Name","value":"records"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"course_session_id"}},{"kind":"Field","name":{"kind":"Name","value":"generation"}},{"kind":"Field","name":{"kind":"Name","value":"circle_id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"success_count"}},{"kind":"Field","name":{"kind":"Name","value":"fail_count"}},{"kind":"Field","name":{"kind":"Name","value":"details_url"}}]}}]}}]}}]}}]} as unknown as DocumentNode;
export const SendFeedbackMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SendFeedbackMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"learningContentType"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"GenericScalar"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"submitted"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"send_feedback"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}},{"kind":"Argument","name":{"kind":"Name","value":"learning_content_page_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"learning_content_type"},"value":{"kind":"Variable","name":{"kind":"Name","value":"learningContentType"}}},{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}},{"kind":"Argument","name":{"kind":"Name","value":"submitted"},"value":{"kind":"Variable","name":{"kind":"Name","value":"submitted"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"feedback_response"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"data"}},{"kind":"Field","name":{"kind":"Name","value":"submitted"}}]}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"field"}},{"kind":"Field","name":{"kind":"Name","value":"messages"}}]}}]}}]}}]} as unknown as DocumentNode;
\ No newline at end of file
diff --git a/client/src/gql/schema.graphql b/client/src/gql/schema.graphql
index 4c421b9b..7bda685a 100644
--- a/client/src/gql/schema.graphql
+++ b/client/src/gql/schema.graphql
@@ -2,6 +2,7 @@ type Query {
course_statistics(course_id: ID!): CourseStatisticsType
course_progress(course_id: ID!): CourseProgressType
dashboard_config: [DashboardConfigType!]!
+ dashboard_data(course_id: ID!): DashboardConfigType
learning_path(id: ID, slug: String, course_id: ID, course_slug: String): LearningPathObjectType
course_session_attendance_course(id: ID!, assignment_user_id: ID): CourseSessionAttendanceCourseObjectType
course(id: ID, slug: String): CourseObjectType
@@ -177,8 +178,9 @@ type CourseProgressType {
_id: ID!
course_id: ID!
session_to_continue_id: ID
- competence: ProgressDashboardCompetenceType!
- assignment: ProgressDashboardAssignmentType!
+ competence: ProgressDashboardCompetenceType
+ assignment: ProgressDashboardAssignmentType
+ widgets: [WidgetType!]!
}
type ProgressDashboardCompetenceType {
@@ -195,6 +197,14 @@ type ProgressDashboardAssignmentType {
points_achieved_count: Int!
}
+enum WidgetType {
+ PROGRESS_WIDGET
+ COMPETENCE_WIDGET
+ MENTEE_WIDGET
+ MENTOR_TASKS_WIDGET
+ COMPETENCE_CERTIFICATE_WIDGET
+}
+
type DashboardConfigType {
id: ID!
name: String!
diff --git a/client/src/gql/typenames.ts b/client/src/gql/typenames.ts
index 5fb963dc..732cb885 100644
--- a/client/src/gql/typenames.ts
+++ b/client/src/gql/typenames.ts
@@ -84,3 +84,4 @@ export const String = "String";
export const TopicObjectType = "TopicObjectType";
export const UUID = "UUID";
export const UserObjectType = "UserObjectType";
+export const WidgetType = "WidgetType";
diff --git a/client/src/graphql/queries.ts b/client/src/graphql/queries.ts
index df6f5259..15dc2766 100644
--- a/client/src/graphql/queries.ts
+++ b/client/src/graphql/queries.ts
@@ -331,6 +331,17 @@ export const DASHBOARD_COURSE_SESSION_PROGRESS = graphql(`
}
`);
+export const DASHBOARD_COURSE_DATA = graphql(`
+ query dashboardCourseData($courseId: ID!) {
+ course_progress(course_id: $courseId) {
+ _id
+ course_id
+ session_to_continue_id
+ widgets
+ }
+ }
+`);
+
export const DASHBOARD_COURSE_STATISTICS = graphql(`
query courseStatistics($courseId: ID!) {
course_statistics(course_id: $courseId) {
diff --git a/client/src/pages/dashboard/DashboardPage.vue b/client/src/pages/dashboard/DashboardPage.vue
index a882818e..cbe936fd 100644
--- a/client/src/pages/dashboard/DashboardPage.vue
+++ b/client/src/pages/dashboard/DashboardPage.vue
@@ -12,6 +12,7 @@ import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
import CourseDetailDates from "@/components/dashboard/CourseDetailDates.vue";
import NoCourseSession from "@/components/dashboard/NoCourseSession.vue";
import MentorPage from "@/pages/dashboard/MentorPage.vue";
+import CoursePanel from "@/components/dashboard/CoursePanel.vue";
const dashboardStore = useDashboardStore();
@@ -50,6 +51,12 @@ onMounted(dashboardStore.loadDashboardDetails);
>
+
diff --git a/client/src/router/guards.ts b/client/src/router/guards.ts
index 089ac20a..8ee4825a 100644
--- a/client/src/router/guards.ts
+++ b/client/src/router/guards.ts
@@ -62,6 +62,7 @@ export async function handleCurrentCourseSession(to: RouteLocationNormalized) {
courseSessionsStore._currentCourseSlug = "";
}
if (!courseSessionsStore.loaded) {
+ console.log("handleCurrentCourseSession: loadCourseSessionsData");
await courseSessionsStore.loadCourseSessionsData();
}
}
@@ -77,6 +78,7 @@ export async function handleCourseSessionAsQueryParam(to: RouteLocationNormalize
if (userStore.loggedIn) {
const courseSessionsStore = useCourseSessionsStore();
if (!courseSessionsStore.loaded) {
+ console.log("handleCourseSessionAsQueryParam: loadCourseSessionsData");
await courseSessionsStore.loadCourseSessionsData();
}
diff --git a/client/src/router/index.ts b/client/src/router/index.ts
index 52a39878..14c9eb43 100644
--- a/client/src/router/index.ts
+++ b/client/src/router/index.ts
@@ -387,8 +387,25 @@ router.beforeEach(updateLoggedIn);
router.beforeEach(redirectToLoginIfRequired);
// register after login hooks
-router.beforeEach(handleCurrentCourseSession);
-router.beforeEach(handleCourseSessionAsQueryParam);
+router.beforeEach(
+ async (to, from) =>
+ await ignoreGuardsForHomeRoute(to, from, handleCurrentCourseSession)
+);
+
+router.beforeEach(
+ async (to, from) =>
+ await ignoreGuardsForHomeRoute(to, from, handleCourseSessionAsQueryParam)
+);
+
+async function ignoreGuardsForHomeRoute(
+ to: RouteLocationNormalized,
+ from: RouteLocationNormalized,
+ guard: NavigationGuardNext
+) {
+ if (to.name !== "home") {
+ return await guard(to, from);
+ }
+}
router.beforeEach(addToHistory);
diff --git a/client/src/services/dashboard.ts b/client/src/services/dashboard.ts
index a320774f..b4232d64 100644
--- a/client/src/services/dashboard.ts
+++ b/client/src/services/dashboard.ts
@@ -1,6 +1,7 @@
import { graphqlClient } from "@/graphql/client";
import {
DASHBOARD_CONFIG,
+ DASHBOARD_COURSE_DATA,
DASHBOARD_COURSE_SESSION_PROGRESS,
DASHBOARD_COURSE_STATISTICS,
} from "@/graphql/queries";
@@ -61,3 +62,21 @@ export const fetchDashboardConfig = async (): Promise => {
+ try {
+ const res = await graphqlClient.query(DASHBOARD_COURSE_DATA, {
+ courseId,
+ });
+
+ if (res.error) {
+ console.error("Error fetching data for course ID:", courseId, res.error);
+ }
+ return res.data?.course_progress || null;
+ } catch (error) {
+ console.error(`Error fetching data for course ID: ${courseId}`, error);
+ return null;
+ }
+};
diff --git a/server/vbv_lernwelt/dashboard/graphql/queries.py b/server/vbv_lernwelt/dashboard/graphql/queries.py
index 38c3c71f..72ee4234 100644
--- a/server/vbv_lernwelt/dashboard/graphql/queries.py
+++ b/server/vbv_lernwelt/dashboard/graphql/queries.py
@@ -17,6 +17,7 @@ from vbv_lernwelt.dashboard.graphql.types.dashboard import (
DashboardType,
ProgressDashboardAssignmentType,
ProgressDashboardCompetenceType,
+ WidgetType,
)
from vbv_lernwelt.iam.permissions import (
can_view_course_session,
@@ -39,6 +40,10 @@ class DashboardQuery(graphene.ObjectType):
graphene.NonNull(DashboardConfigType), required=True
)
+ dashboard_data = graphene.Field(
+ DashboardConfigType, course_id=graphene.ID(required=True)
+ )
+
def resolve_course_statistics(root, info, course_id: str): # noqa
user = info.context.user
course = Course.objects.get(id=course_id)
@@ -164,8 +169,12 @@ class DashboardQuery(graphene.ObjectType):
points_max_count=int(points_max_count), # noqa
points_achieved_count=int(points_achieved_count), # noqa
),
+ widgets=get_widget_for_course(course_id, user), # noqa
)
+ def resolve_dashboard_data(root, info, course_id: str):
+ return get_widget_for_course(course_id, info.context.user)
+
def get_user_statistics_dashboards(user: User) -> Tuple[List[Dict[str, str]], Set[int]]:
course_ids = set()
@@ -222,7 +231,6 @@ def get_user_course_session_dashboards(
sessions of a course, but with varying permissions?
-> We just show the simple list dashboard for now.
"""
-
dashboards = []
course_ids = set()
@@ -246,6 +254,7 @@ def get_user_course_session_dashboards(
resolved_dashboard_type = DashboardType.SIMPLE_DASHBOARD
elif course_role == CourseSessionUser.Role.MEMBER:
resolved_dashboard_type = DashboardType.PROGRESS_DASHBOARD
+
else:
# fallback: just go with simple list dashboard
resolved_dashboard_type = DashboardType.SIMPLE_DASHBOARD
@@ -263,3 +272,42 @@ def get_user_course_session_dashboards(
)
return dashboards, course_ids
+
+
+def get_widget_for_course(course_id: str, user: User) -> List[WidgetType]:
+ widgets = []
+
+ course_sessions = CourseSession.objects.filter(course__id=course_id).prefetch_related(
+ "course",
+ "course__configuration",
+ )
+ roles_by_course: Dict[Course, Set[DashboardType]] = {}
+
+ learning_mentors = LearningMentor.objects.filter(mentor=user).values_list(
+ "course_session__course__id", "id"
+ )
+ mentor_course_ids = set([mentor[0] for mentor in learning_mentors])
+
+ # duplicate code
+ for course_session in course_sessions:
+ if can_view_course_session(user=user, course_session=course_session):
+ role = CourseSessionUser.objects.get(
+ course_session=course_session, user=user
+ ).role
+ roles_by_course.setdefault(course_session.course, set())
+ roles_by_course[course_session.course].add(role)
+
+ for course, roles in roles_by_course.items():
+ if len(roles) == 1:
+ course_role = roles.pop()
+
+ # test widgets
+ if course_role == CourseSessionUser.Role.MEMBER:
+ widgets.append(WidgetType.PROGRESS_WIDGET)
+ widgets.append(WidgetType.COMPETENCE_WIDGET)
+ if course.configuration.enable_competence_certificates:
+ widgets.append(WidgetType.COMPETENCE_CERTIFICATE_WIDGET)
+ if course.id in mentor_course_ids:
+ widgets.append(WidgetType.MENTOR_TASKS_WIDGET)
+ # add KN if has KN
+ return widgets
diff --git a/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py b/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py
index 2ad4d5de..35648f76 100644
--- a/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py
+++ b/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py
@@ -56,6 +56,14 @@ class DashboardType(Enum):
MENTOR_DASHBOARD = "MentorDashboard"
+class WidgetType(Enum):
+ PROGRESS_WIDGET = "ProgressWidget"
+ COMPETENCE_WIDGET = "CompetenceWidget"
+ MENTEE_WIDGET = "MenteeWidget"
+ MENTOR_TASKS_WIDGET = "MentorTasksWidget"
+ COMPETENCE_CERTIFICATE_WIDGET = "CompetenceCertificateWidget"
+
+
class DashboardConfigType(graphene.ObjectType):
id = graphene.ID(required=True)
name = graphene.String(required=True)
@@ -64,6 +72,11 @@ class DashboardConfigType(graphene.ObjectType):
course_configuration = graphene.Field(CourseConfigurationObjectType, required=True)
+class DashboardDataType(graphene.ObjectType):
+ id = graphene.ID(required=True)
+ widgets = graphene.List(graphene.NonNull(WidgetType), required=True)
+
+
class ProgressDashboardCompetenceType(graphene.ObjectType):
_id = graphene.ID(required=True)
total_count = graphene.Int(required=True)
@@ -82,8 +95,9 @@ class CourseProgressType(graphene.ObjectType):
_id = graphene.ID(required=True)
course_id = graphene.ID(required=True)
session_to_continue_id = graphene.ID(required=False)
- competence = graphene.Field(ProgressDashboardCompetenceType, required=True)
- assignment = graphene.Field(ProgressDashboardAssignmentType, required=True)
+ competence = graphene.Field(ProgressDashboardCompetenceType, required=False)
+ assignment = graphene.Field(ProgressDashboardAssignmentType, required=False)
+ widgets = graphene.List(graphene.NonNull(WidgetType), required=True)
class CourseStatisticsType(graphene.ObjectType):