feat: stats dashboard
This commit is contained in:
parent
ae4f4d2611
commit
d66e392c73
|
|
@ -22,7 +22,8 @@ const 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": types.CourseSessionDetailDocument,
|
||||
"\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\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 }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n has_extended_time_test\n content_assignment {\n id\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 }\n }\n": types.DashboardConfigDocument,
|
||||
"\n query dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n 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 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 courseStatistics($course_id: ID!) {\n course_statistics(course_id: $course_id) {\n _id\n course_id\n course_title\n course_slug\n course_session_properties {\n _id\n sessions {\n _id\n session_id\n session_title\n }\n generations\n circles {\n _id\n circle_id\n circle_title\n experts\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 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 performances {\n _id\n course_session_id\n generation\n circle_id\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 $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,
|
||||
};
|
||||
|
||||
|
|
@ -79,7 +80,11 @@ 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 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 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"];
|
||||
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 courseStatistics($course_id: ID!) {\n course_statistics(course_id: $course_id) {\n _id\n course_id\n course_title\n course_slug\n course_session_properties {\n _id\n sessions {\n _id\n session_id\n session_title\n }\n generations\n circles {\n _id\n circle_id\n circle_title\n experts\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 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 performances {\n _id\n course_session_id\n generation\n circle_id\n success_count\n fail_count\n details_url\n }\n }\n }\n }\n"): (typeof documents)["\n query courseStatistics($course_id: ID!) {\n course_statistics(course_id: $course_id) {\n _id\n course_id\n course_title\n course_slug\n course_session_properties {\n _id\n sessions {\n _id\n session_id\n session_title\n }\n generations\n circles {\n _id\n circle_id\n circle_title\n experts\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 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 performances {\n _id\n course_session_id\n generation\n circle_id\n success_count\n fail_count\n details_url\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
|
|
@ -23,47 +23,54 @@ type Query {
|
|||
}
|
||||
|
||||
type CourseStatisticsType {
|
||||
id: ID!
|
||||
_id: ID!
|
||||
course_id: ID!
|
||||
course_title: String!
|
||||
course_slug: String!
|
||||
course_session_properties: CourseSessionProperties!
|
||||
course_session_properties: StatisticsCourseSessionPropertiesType!
|
||||
course_session_selection_ids: [ID]!
|
||||
course_session_selection_metrics: CourseSessionsSelectionMetrics!
|
||||
attendance_day_presences: AttendanceDayPresences!
|
||||
feedback_responses: FeedbackResponses!
|
||||
assignments: Assignments!
|
||||
competences: Competences!
|
||||
course_session_selection_metrics: StatisticsCourseSessionsSelectionMetricType!
|
||||
attendance_day_presences: AttendanceDayPresencesStatisticsType!
|
||||
feedback_responses: FeedbackStatisticsResponsesType!
|
||||
assignments: AssignmentsStatisticsType!
|
||||
competences: CompetencesStatisticsType!
|
||||
}
|
||||
|
||||
type CourseSessionProperties {
|
||||
sessions: [CourseSessionData]!
|
||||
type StatisticsCourseSessionPropertiesType {
|
||||
_id: ID!
|
||||
sessions: [StatisticsCourseSessionDataType]!
|
||||
generations: [String]!
|
||||
circles: [CircleData]!
|
||||
circles: [StatisticsCircleDataType]!
|
||||
}
|
||||
|
||||
type CourseSessionData {
|
||||
type StatisticsCourseSessionDataType {
|
||||
_id: ID!
|
||||
session_id: ID!
|
||||
session_title: String!
|
||||
}
|
||||
|
||||
type CircleData {
|
||||
type StatisticsCircleDataType {
|
||||
_id: ID!
|
||||
circle_id: ID!
|
||||
circle_title: String!
|
||||
experts: [String]!
|
||||
}
|
||||
|
||||
type CourseSessionsSelectionMetrics {
|
||||
type StatisticsCourseSessionsSelectionMetricType {
|
||||
_id: ID!
|
||||
session_count: Int!
|
||||
participant_count: Int!
|
||||
expert_count: Int!
|
||||
}
|
||||
|
||||
type AttendanceDayPresences {
|
||||
records: [PresenceRecord]!
|
||||
summary: AttendanceSummary!
|
||||
type AttendanceDayPresencesStatisticsType {
|
||||
_id: ID!
|
||||
records: [PresenceRecordStatisticsType]!
|
||||
summary: AttendanceSummaryStatisticsType!
|
||||
}
|
||||
|
||||
type PresenceRecord {
|
||||
type PresenceRecordStatisticsType {
|
||||
_id: ID!
|
||||
course_session_id: ID!
|
||||
generation: String!
|
||||
circle_id: ID!
|
||||
|
|
@ -73,17 +80,20 @@ type PresenceRecord {
|
|||
details_url: String!
|
||||
}
|
||||
|
||||
type AttendanceSummary {
|
||||
type AttendanceSummaryStatisticsType {
|
||||
_id: ID!
|
||||
days_completed: Int!
|
||||
participants_present: Int!
|
||||
}
|
||||
|
||||
type FeedbackResponses {
|
||||
records: [FeedbackRecord]!
|
||||
summary: FeedbackSummary!
|
||||
type FeedbackStatisticsResponsesType {
|
||||
_id: ID!
|
||||
records: [FeedbackStatisticsRecordType]!
|
||||
summary: FeedbackStatisticsSummaryType!
|
||||
}
|
||||
|
||||
type FeedbackRecord {
|
||||
type FeedbackStatisticsRecordType {
|
||||
_id: ID!
|
||||
course_session_id: ID!
|
||||
generation: String!
|
||||
circle_id: ID!
|
||||
|
|
@ -92,18 +102,21 @@ type FeedbackRecord {
|
|||
details_url: String!
|
||||
}
|
||||
|
||||
type FeedbackSummary {
|
||||
type FeedbackStatisticsSummaryType {
|
||||
_id: ID!
|
||||
satisfaction_average: Float!
|
||||
satisfaction_max: Int!
|
||||
total_responses: Int!
|
||||
}
|
||||
|
||||
type Assignments {
|
||||
records: [AssignmentRecord]!
|
||||
summary: AssignmentSummary!
|
||||
type AssignmentsStatisticsType {
|
||||
_id: ID!
|
||||
records: [AssignmentStatisticsRecordType]!
|
||||
summary: AssignmentStatisticsSummaryType!
|
||||
}
|
||||
|
||||
type AssignmentRecord {
|
||||
type AssignmentStatisticsRecordType {
|
||||
_id: ID!
|
||||
course_session_id: ID!
|
||||
course_session_assignment_id: ID!
|
||||
circle_id: ID!
|
||||
|
|
@ -111,7 +124,7 @@ type AssignmentRecord {
|
|||
assignment_type_translation_key: String!
|
||||
assignment_title: String!
|
||||
deadline: DateTime!
|
||||
metrics: AssignmentCompletionMetrics!
|
||||
metrics: AssignmentCompletionMetricsType!
|
||||
details_url: String!
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +135,8 @@ value as specified by
|
|||
"""
|
||||
scalar DateTime
|
||||
|
||||
type AssignmentCompletionMetrics {
|
||||
type AssignmentCompletionMetricsType {
|
||||
_id: ID!
|
||||
passed_count: Int!
|
||||
failed_count: Int!
|
||||
unranked_count: Int!
|
||||
|
|
@ -130,17 +144,26 @@ type AssignmentCompletionMetrics {
|
|||
average_passed: Float!
|
||||
}
|
||||
|
||||
type AssignmentSummary {
|
||||
type AssignmentStatisticsSummaryType {
|
||||
_id: ID!
|
||||
completed_count: Int!
|
||||
average_passed: Float!
|
||||
}
|
||||
|
||||
type Competences {
|
||||
performances: [CompetencePerformance]!
|
||||
summary: CompletionSummary!
|
||||
type CompetencesStatisticsType {
|
||||
_id: ID!
|
||||
summary: CompetencePerformanceStatisticsSummaryType!
|
||||
performances: [CompetencePerformanceStatisticsType]!
|
||||
}
|
||||
|
||||
type CompetencePerformance {
|
||||
type CompetencePerformanceStatisticsSummaryType {
|
||||
_id: ID!
|
||||
success_total: Int!
|
||||
fail_total: Int!
|
||||
}
|
||||
|
||||
type CompetencePerformanceStatisticsType {
|
||||
_id: ID!
|
||||
course_session_id: ID!
|
||||
generation: String!
|
||||
circle_id: ID!
|
||||
|
|
@ -149,13 +172,9 @@ type CompetencePerformance {
|
|||
details_url: String!
|
||||
}
|
||||
|
||||
type CompletionSummary {
|
||||
success_total: Int!
|
||||
fail_total: Int!
|
||||
}
|
||||
|
||||
type CourseProgressType {
|
||||
id: ID!
|
||||
_id: ID!
|
||||
course_id: ID!
|
||||
session_to_continue_id: ID
|
||||
competence: ProgressDashboardCompetenceType!
|
||||
assignment: ProgressDashboardAssignmentType!
|
||||
|
|
|
|||
|
|
@ -1,29 +1,28 @@
|
|||
export const ActionCompetenceObjectType = "ActionCompetenceObjectType";
|
||||
export const AssignmentAssignmentAssignmentTypeChoices = "AssignmentAssignmentAssignmentTypeChoices";
|
||||
export const AssignmentAssignmentCompletionCompletionStatusChoices = "AssignmentAssignmentCompletionCompletionStatusChoices";
|
||||
export const AssignmentCompletionMetrics = "AssignmentCompletionMetrics";
|
||||
export const AssignmentCompletionMetricsType = "AssignmentCompletionMetricsType";
|
||||
export const AssignmentCompletionMutation = "AssignmentCompletionMutation";
|
||||
export const AssignmentCompletionObjectType = "AssignmentCompletionObjectType";
|
||||
export const AssignmentCompletionStatus = "AssignmentCompletionStatus";
|
||||
export const AssignmentObjectType = "AssignmentObjectType";
|
||||
export const AssignmentRecord = "AssignmentRecord";
|
||||
export const AssignmentSummary = "AssignmentSummary";
|
||||
export const Assignments = "Assignments";
|
||||
export const AssignmentStatisticsRecordType = "AssignmentStatisticsRecordType";
|
||||
export const AssignmentStatisticsSummaryType = "AssignmentStatisticsSummaryType";
|
||||
export const AssignmentsStatisticsType = "AssignmentsStatisticsType";
|
||||
export const AttendanceCourseUserMutation = "AttendanceCourseUserMutation";
|
||||
export const AttendanceDayPresences = "AttendanceDayPresences";
|
||||
export const AttendanceSummary = "AttendanceSummary";
|
||||
export const AttendanceDayPresencesStatisticsType = "AttendanceDayPresencesStatisticsType";
|
||||
export const AttendanceSummaryStatisticsType = "AttendanceSummaryStatisticsType";
|
||||
export const AttendanceUserInputType = "AttendanceUserInputType";
|
||||
export const AttendanceUserObjectType = "AttendanceUserObjectType";
|
||||
export const AttendanceUserStatus = "AttendanceUserStatus";
|
||||
export const Boolean = "Boolean";
|
||||
export const CircleData = "CircleData";
|
||||
export const CircleLightObjectType = "CircleLightObjectType";
|
||||
export const CircleObjectType = "CircleObjectType";
|
||||
export const CompetenceCertificateListObjectType = "CompetenceCertificateListObjectType";
|
||||
export const CompetenceCertificateObjectType = "CompetenceCertificateObjectType";
|
||||
export const CompetencePerformance = "CompetencePerformance";
|
||||
export const Competences = "Competences";
|
||||
export const CompletionSummary = "CompletionSummary";
|
||||
export const CompetencePerformanceStatisticsSummaryType = "CompetencePerformanceStatisticsSummaryType";
|
||||
export const CompetencePerformanceStatisticsType = "CompetencePerformanceStatisticsType";
|
||||
export const CompetencesStatisticsType = "CompetencesStatisticsType";
|
||||
export const CoreUserLanguageChoices = "CoreUserLanguageChoices";
|
||||
export const CourseCourseSessionUserRoleChoices = "CourseCourseSessionUserRoleChoices";
|
||||
export const CourseObjectType = "CourseObjectType";
|
||||
|
|
@ -31,13 +30,10 @@ export const CoursePageInterface = "CoursePageInterface";
|
|||
export const CourseProgressType = "CourseProgressType";
|
||||
export const CourseSessionAssignmentObjectType = "CourseSessionAssignmentObjectType";
|
||||
export const CourseSessionAttendanceCourseObjectType = "CourseSessionAttendanceCourseObjectType";
|
||||
export const CourseSessionData = "CourseSessionData";
|
||||
export const CourseSessionEdoniqTestObjectType = "CourseSessionEdoniqTestObjectType";
|
||||
export const CourseSessionObjectType = "CourseSessionObjectType";
|
||||
export const CourseSessionProperties = "CourseSessionProperties";
|
||||
export const CourseSessionUserExpertCircleType = "CourseSessionUserExpertCircleType";
|
||||
export const CourseSessionUserObjectsType = "CourseSessionUserObjectsType";
|
||||
export const CourseSessionsSelectionMetrics = "CourseSessionsSelectionMetrics";
|
||||
export const CourseStatisticsType = "CourseStatisticsType";
|
||||
export const DashboardConfigType = "DashboardConfigType";
|
||||
export const DashboardType = "DashboardType";
|
||||
|
|
@ -45,10 +41,10 @@ export const Date = "Date";
|
|||
export const DateTime = "DateTime";
|
||||
export const DueDateObjectType = "DueDateObjectType";
|
||||
export const ErrorType = "ErrorType";
|
||||
export const FeedbackRecord = "FeedbackRecord";
|
||||
export const FeedbackResponseObjectType = "FeedbackResponseObjectType";
|
||||
export const FeedbackResponses = "FeedbackResponses";
|
||||
export const FeedbackSummary = "FeedbackSummary";
|
||||
export const FeedbackStatisticsRecordType = "FeedbackStatisticsRecordType";
|
||||
export const FeedbackStatisticsResponsesType = "FeedbackStatisticsResponsesType";
|
||||
export const FeedbackStatisticsSummaryType = "FeedbackStatisticsSummaryType";
|
||||
export const Float = "Float";
|
||||
export const GenericScalar = "GenericScalar";
|
||||
export const ID = "ID";
|
||||
|
|
@ -72,11 +68,15 @@ export const LearningUnitObjectType = "LearningUnitObjectType";
|
|||
export const LearnpathLearningContentAssignmentAssignmentTypeChoices = "LearnpathLearningContentAssignmentAssignmentTypeChoices";
|
||||
export const Mutation = "Mutation";
|
||||
export const PerformanceCriteriaObjectType = "PerformanceCriteriaObjectType";
|
||||
export const PresenceRecord = "PresenceRecord";
|
||||
export const PresenceRecordStatisticsType = "PresenceRecordStatisticsType";
|
||||
export const ProgressDashboardAssignmentType = "ProgressDashboardAssignmentType";
|
||||
export const ProgressDashboardCompetenceType = "ProgressDashboardCompetenceType";
|
||||
export const Query = "Query";
|
||||
export const SendFeedbackMutation = "SendFeedbackMutation";
|
||||
export const StatisticsCircleDataType = "StatisticsCircleDataType";
|
||||
export const StatisticsCourseSessionDataType = "StatisticsCourseSessionDataType";
|
||||
export const StatisticsCourseSessionPropertiesType = "StatisticsCourseSessionPropertiesType";
|
||||
export const StatisticsCourseSessionsSelectionMetricType = "StatisticsCourseSessionsSelectionMetricType";
|
||||
export const String = "String";
|
||||
export const TopicObjectType = "TopicObjectType";
|
||||
export const UUID = "UUID";
|
||||
|
|
|
|||
|
|
@ -283,7 +283,8 @@ export const DASHBOARD_CONFIG = graphql(`
|
|||
export const DASHBOARD_COURSE_SESSION_PROGRESS = graphql(`
|
||||
query dashboardProgress($courseId: ID!) {
|
||||
course_progress(course_id: $courseId) {
|
||||
id
|
||||
_id
|
||||
course_id
|
||||
session_to_continue_id
|
||||
competence {
|
||||
_id
|
||||
|
|
@ -300,3 +301,116 @@ export const DASHBOARD_COURSE_SESSION_PROGRESS = graphql(`
|
|||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const DASHBOARD_COURSE_STATISTICS = graphql(`
|
||||
query courseStatistics($course_id: ID!) {
|
||||
course_statistics(course_id: $course_id) {
|
||||
_id
|
||||
course_id
|
||||
course_title
|
||||
course_slug
|
||||
course_session_properties {
|
||||
_id
|
||||
sessions {
|
||||
_id
|
||||
session_id
|
||||
session_title
|
||||
}
|
||||
generations
|
||||
circles {
|
||||
_id
|
||||
circle_id
|
||||
circle_title
|
||||
experts
|
||||
}
|
||||
}
|
||||
course_session_selection_ids
|
||||
course_session_selection_metrics {
|
||||
_id
|
||||
session_count
|
||||
participant_count
|
||||
expert_count
|
||||
}
|
||||
attendance_day_presences {
|
||||
_id
|
||||
records {
|
||||
_id
|
||||
course_session_id
|
||||
generation
|
||||
circle_id
|
||||
due_date
|
||||
participants_present
|
||||
participants_total
|
||||
details_url
|
||||
}
|
||||
summary {
|
||||
_id
|
||||
days_completed
|
||||
participants_present
|
||||
}
|
||||
}
|
||||
feedback_responses {
|
||||
_id
|
||||
records {
|
||||
_id
|
||||
course_session_id
|
||||
generation
|
||||
circle_id
|
||||
satisfaction_average
|
||||
satisfaction_max
|
||||
details_url
|
||||
}
|
||||
summary {
|
||||
_id
|
||||
satisfaction_average
|
||||
satisfaction_max
|
||||
total_responses
|
||||
}
|
||||
}
|
||||
assignments {
|
||||
_id
|
||||
summary {
|
||||
_id
|
||||
completed_count
|
||||
average_passed
|
||||
}
|
||||
records {
|
||||
_id
|
||||
course_session_id
|
||||
course_session_assignment_id
|
||||
circle_id
|
||||
generation
|
||||
assignment_title
|
||||
assignment_type_translation_key
|
||||
details_url
|
||||
deadline
|
||||
metrics {
|
||||
_id
|
||||
passed_count
|
||||
failed_count
|
||||
unranked_count
|
||||
ranking_completed
|
||||
average_passed
|
||||
}
|
||||
}
|
||||
}
|
||||
competences {
|
||||
_id
|
||||
summary {
|
||||
_id
|
||||
success_total
|
||||
fail_total
|
||||
}
|
||||
performances {
|
||||
_id
|
||||
course_session_id
|
||||
generation
|
||||
circle_id
|
||||
success_count
|
||||
fail_count
|
||||
details_url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
|
|
|||
|
|
@ -47,66 +47,89 @@ const assignment_progress = computed(() => ({
|
|||
FAIL: 0,
|
||||
UNKNOWN: assignment.value.points_max_count - assignment.value.points_achieved_count,
|
||||
}));
|
||||
|
||||
const competenceCertificateUrl = computed(() => {
|
||||
return `/course/${courseSlug.value}/competence/certificates?courseSessionId=${progress.value?.course_progress?.session_to_continue_id}`;
|
||||
});
|
||||
|
||||
const competenceCriteriaUrl = computed(() => {
|
||||
return `/course/${courseSlug.value}/competence/criteria?courseSessionId=${progress.value?.course_progress?.session_to_continue_id}`;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="progress?.course_progress && dashboardStore.currentDashboardConfig">
|
||||
<div class="mb-14 space-y-8">
|
||||
<div class="flex flex-col space-y-7 bg-white p-6">
|
||||
<h3>{{ courseName }}</h3>
|
||||
<LearningPathDiagram
|
||||
v-if="progress.course_progress.session_to_continue_id && courseSlug"
|
||||
:key="courseSlug"
|
||||
:course-slug="courseSlug"
|
||||
:course-session-id="progress.course_progress.session_to_continue_id"
|
||||
diagram-type="horizontal"
|
||||
></LearningPathDiagram>
|
||||
<div>
|
||||
<router-link
|
||||
class="btn-blue"
|
||||
:to="getLearningPathUrl(dashboardStore.currentDashboardConfig.slug)"
|
||||
:data-cy="`continue-course-${dashboardStore.currentDashboardConfig.id}`"
|
||||
>
|
||||
{{ $t("general.nextStep") }}
|
||||
</router-link>
|
||||
</div>
|
||||
<div
|
||||
v-if="progress?.course_progress && dashboardStore.currentDashboardConfig"
|
||||
class="mb-14 space-y-8"
|
||||
>
|
||||
<div class="flex flex-col space-y-7 bg-white p-6">
|
||||
<h3>{{ courseName }}</h3>
|
||||
<LearningPathDiagram
|
||||
v-if="progress.course_progress.session_to_continue_id && courseSlug"
|
||||
:key="courseSlug"
|
||||
:course-slug="courseSlug"
|
||||
:course-session-id="progress.course_progress.session_to_continue_id"
|
||||
diagram-type="horizontal"
|
||||
></LearningPathDiagram>
|
||||
<div>
|
||||
<router-link
|
||||
class="btn-blue"
|
||||
:to="getLearningPathUrl(dashboardStore.currentDashboardConfig.slug)"
|
||||
:data-cy="`continue-course-${dashboardStore.currentDashboardConfig.id}`"
|
||||
>
|
||||
{{ $t("general.nextStep") }}
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="grid auto-rows-fr grid-cols-1 gap-8 xl:grid-cols-2">
|
||||
<div class="flex flex-col space-y-4 bg-white p-6">
|
||||
<h4 class="mb-1 font-bold">Kompetenznachweis-Elemente</h4>
|
||||
<div class="flex items-center space-x-3">
|
||||
<span class="text-4xl font-bold">
|
||||
{{ assignment.total_count }}
|
||||
</span>
|
||||
<span>Elemente abgeschlossen</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-3">
|
||||
<span class="text-4xl font-bold">
|
||||
{{ assignment.points_achieved_count }} von
|
||||
{{ assignment.points_max_count }}
|
||||
</span>
|
||||
<span>Punkten erreicht</span>
|
||||
</div>
|
||||
<ItProgress :status-count="assignment_progress"></ItProgress>
|
||||
|
||||
<router-link class="pt-8 underline" to="#">Details anschauen</router-link>
|
||||
</div>
|
||||
<div class="grid auto-rows-fr grid-cols-1 gap-8 xl:grid-cols-2">
|
||||
<div class="flex flex-col space-y-4 bg-white p-6">
|
||||
<h4 class="mb-1 font-bold">{{ $t("a.Kompetenznachweis-Elemente") }}</h4>
|
||||
<div class="flex items-center">
|
||||
<i18next :translation="$t('a.NUMBER Elemente abgeschlossen')">
|
||||
<template #NUMBER>
|
||||
<span class="mr-3 text-4xl font-bold">
|
||||
{{ assignment.total_count }}
|
||||
</span>
|
||||
</template>
|
||||
</i18next>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col space-y-4 bg-white p-6">
|
||||
<h4 class="mb-1 font-bold">Selbsteinschätzungen</h4>
|
||||
<div class="flex items-center space-x-3">
|
||||
<it-icon-smiley-happy class="h-12 w-12"></it-icon-smiley-happy>
|
||||
<span class="text-4xl font-bold">{{ competence.success_count }}</span>
|
||||
<span>Ich kann das</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-3">
|
||||
<it-icon-smiley-thinking class="h-12 w-12"></it-icon-smiley-thinking>
|
||||
<span class="text-4xl font-bold">{{ competence.fail_count }}</span>
|
||||
<span>Das muss ich nochmals anschauen</span>
|
||||
</div>
|
||||
<router-link class="pt-8 underline" to="#">Details anschauen</router-link>
|
||||
<div class="flex items-center">
|
||||
<i18next :translation="$t('a.xOfY Punkten erreicht')">
|
||||
<template #xOfY>
|
||||
<span class="mr-3 text-4xl font-bold">
|
||||
{{
|
||||
$t("a.VALUE von MAXIMUM", {
|
||||
VALUE: assignment.points_achieved_count,
|
||||
MAXIMUM: assignment.points_max_count,
|
||||
})
|
||||
}}
|
||||
</span>
|
||||
</template>
|
||||
</i18next>
|
||||
</div>
|
||||
<ItProgress :status-count="assignment_progress"></ItProgress>
|
||||
|
||||
<router-link class="pt-8 underline" :to="competenceCertificateUrl">
|
||||
{{ $t("a.Details anschauen") }}
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col space-y-4 bg-white p-6">
|
||||
<h4 class="mb-1 font-bold">{{ $t("a.Selbsteinschätzungen") }}</h4>
|
||||
<div class="flex items-center space-x-3">
|
||||
<it-icon-smiley-happy class="h-12 w-12"></it-icon-smiley-happy>
|
||||
<span class="text-4xl font-bold">{{ competence.success_count }}</span>
|
||||
<span>{{ $t("a.Ich kann das") }}</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-3">
|
||||
<it-icon-smiley-thinking class="h-12 w-12"></it-icon-smiley-thinking>
|
||||
<span class="text-4xl font-bold">{{ competence.fail_count }}</span>
|
||||
<span>{{ $t("a.Das muss ich nochmals anschauen") }}</span>
|
||||
</div>
|
||||
<router-link class="pt-8 underline" :to="competenceCriteriaUrl">
|
||||
{{ $t("a.Details anschauen") }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,63 @@
|
|||
<script setup lang="ts"></script>
|
||||
<script setup lang="ts">
|
||||
import { useDashboardStore } from "@/stores/dashboard";
|
||||
import { onMounted } from "vue";
|
||||
import ItProgress from "@/components/ui/ItProgress.vue";
|
||||
|
||||
const dashboardStore = useDashboardStore();
|
||||
|
||||
onMounted(dashboardStore.loadDashboardStatistics);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h4>Stats</h4>
|
||||
<div v-if="dashboardStore.currentCourseStatistics" class="mb-14 space-y-8">
|
||||
<div class="flex items-center justify-between bg-white p-6">
|
||||
<div class="flex space-x-6">
|
||||
<div class="flex items-center space-x-2">
|
||||
<span class="text-4xl font-bold">352</span>
|
||||
<span>Teilnehmer</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<span class="text-4xl font-bold">25</span>
|
||||
<span>Trainer</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<span class="text-4xl font-bold">18</span>
|
||||
<span>Durchführungen</span>
|
||||
</div>
|
||||
</div>
|
||||
<router-link class="btn-secondary" to="#">
|
||||
{{ $t("a.Liste anzeigen") }}
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="grid auto-rows-fr grid-cols-1 gap-8 xl:grid-cols-2">
|
||||
<div class="flex flex-col space-y-4 bg-white p-6">
|
||||
<h4 class="mb-1 font-bold">{{ $t("a.Anwesenheit") }}</h4>
|
||||
<div class="flex items-center">
|
||||
<i18next :translation="$t('a.NUMBER Präsenztage abgeschlossen')">
|
||||
<template #NUMBER>
|
||||
<span class="mr-3 text-4xl font-bold">
|
||||
{{
|
||||
dashboardStore.currentCourseStatistics.attendance_day_presences
|
||||
.summary.days_completed
|
||||
}}
|
||||
</span>
|
||||
</template>
|
||||
</i18next>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i18next :translation="$t('a.NUMBER Präsenztage abgeschlossen')">
|
||||
<template #NUMBER>
|
||||
<span class="mr-3 text-4xl font-bold">
|
||||
{{
|
||||
dashboardStore.currentCourseStatistics.attendance_day_presences
|
||||
.summary.days_completed
|
||||
}}
|
||||
</span>
|
||||
</template>
|
||||
</i18next>
|
||||
</div>
|
||||
<ItProgress></ItProgress>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { DashboardConfigType } from "@/gql/graphql";
|
||||
import type { CourseStatisticsType, DashboardConfigType } from "@/gql/graphql";
|
||||
import { graphqlClient } from "@/graphql/client";
|
||||
import { DASHBOARD_CONFIG } from "@/graphql/queries";
|
||||
import { DASHBOARD_CONFIG, DASHBOARD_COURSE_STATISTICS } from "@/graphql/queries";
|
||||
import { defineStore } from "pinia";
|
||||
import type { Ref } from "vue";
|
||||
import { ref } from "vue";
|
||||
|
|
@ -8,9 +8,14 @@ import { ref } from "vue";
|
|||
export const useDashboardStore = defineStore("dashboard", () => {
|
||||
const dashboardConfigs: Ref<DashboardConfigType[]> = ref([]);
|
||||
const currentDashboardConfig: Ref<DashboardConfigType | undefined> = ref();
|
||||
const courseStatisticsCache: Record<string, CourseStatisticsType | null> = {};
|
||||
const currentCourseStatistics: Ref<CourseStatisticsType | null> = ref(null);
|
||||
|
||||
const setCurrentDashboardConfig = (config: DashboardConfigType) => {
|
||||
const setCurrentDashboardConfig = async (config: DashboardConfigType) => {
|
||||
currentDashboardConfig.value = config;
|
||||
if (config.dashboard_type === "STATISTICS_DASHBOARD") {
|
||||
await loadDashboardStatistics();
|
||||
}
|
||||
};
|
||||
|
||||
const loadDashboardConfig = async () => {
|
||||
|
|
@ -18,6 +23,35 @@ export const useDashboardStore = defineStore("dashboard", () => {
|
|||
if (res.data) {
|
||||
dashboardConfigs.value = res.data.dashboard_config;
|
||||
currentDashboardConfig.value = res.data.dashboard_config[0];
|
||||
} else {
|
||||
console.warn("No dashboard config found");
|
||||
}
|
||||
};
|
||||
|
||||
const loadDashboardStatistics = async () => {
|
||||
if (!currentDashboardConfig.value) {
|
||||
currentCourseStatistics.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
const courseId = currentDashboardConfig.value.id;
|
||||
|
||||
if (courseStatisticsCache[courseId]) {
|
||||
currentCourseStatistics.value = courseStatisticsCache[courseId];
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await graphqlClient.query(DASHBOARD_COURSE_STATISTICS, {
|
||||
course_id: courseId,
|
||||
});
|
||||
|
||||
if (res.data && res.data.course_statistics) {
|
||||
courseStatisticsCache[courseId] = res.data.course_statistics;
|
||||
currentCourseStatistics.value = res.data.course_statistics;
|
||||
} else {
|
||||
console.warn(`No course statistics found for course ID: ${courseId}`);
|
||||
courseStatisticsCache[courseId] = null;
|
||||
currentCourseStatistics.value = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -26,5 +60,7 @@ export const useDashboardStore = defineStore("dashboard", () => {
|
|||
currentDashboardConfig,
|
||||
setCurrentDashboardConfig,
|
||||
loadDashboardConfig,
|
||||
loadDashboardStatistics,
|
||||
currentCourseStatistics,
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class DashboardQuery(graphene.ObjectType):
|
|||
courses = Course.objects.all().values("id", "title", "slug")
|
||||
return [
|
||||
{
|
||||
"_id": c["id"],
|
||||
"id": c["id"],
|
||||
"course_id": c["id"],
|
||||
"name": c["title"],
|
||||
"slug": c["slug"],
|
||||
|
|
|
|||
|
|
@ -58,9 +58,12 @@ def feedback_responses(
|
|||
)
|
||||
)
|
||||
|
||||
avg = sum([fb.satisfaction_average for fb in circle_feedbacks]) / len(
|
||||
circle_feedbacks
|
||||
)
|
||||
if len(circle_feedbacks):
|
||||
avg = sum([fb.satisfaction_average for fb in circle_feedbacks]) / len(
|
||||
circle_feedbacks
|
||||
)
|
||||
else:
|
||||
avg = 0
|
||||
|
||||
return FeedbackStatisticsResponsesType(
|
||||
_id=course_id, # noqa
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ from vbv_lernwelt.dashboard.tests.graphql.utils import (
|
|||
add_course_session_user,
|
||||
create_assignment,
|
||||
create_assignment_completion,
|
||||
create_circle,
|
||||
create_course,
|
||||
create_course_session,
|
||||
create_course_session_group,
|
||||
create_user,
|
||||
create_circle,
|
||||
create_performance_criteria_page,
|
||||
create_user,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue