Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance(apps/analytics): add illustration of individual student performance #4400

Merged
merged 2 commits into from
Dec 19, 2024

Conversation

sjschlapbach
Copy link
Member

@sjschlapbach sjschlapbach commented Dec 19, 2024

Summary by CodeRabbit

  • New Features

    • Introduced a new component for visualizing student performance data with a bar chart and data table.
    • Added a custom hook for processing participant performance data into a histogram format.
    • Expanded GraphQL query to include detailed participant performance metrics.
  • Bug Fixes

    • Enhanced error handling and input flexibility in analytics functions.
  • Documentation

    • Updated localization files to improve clarity and accuracy of user interface messages.
  • Refactor

    • Renamed components and variables for consistency and clarity, including updates to function signatures.
  • Chores

    • Updated GraphQL schema and client configurations to reflect new data structures.

Copy link

coderabbitai bot commented Dec 19, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

This pull request introduces comprehensive enhancements to the performance analytics system in the KlickerUZH application. The changes span multiple files across frontend components, GraphQL schema, internationalization, and type definitions. The primary focus is on adding detailed participant performance tracking, introducing new visualization components for performance metrics, and refactoring existing analytics-related code to support more granular performance analysis.

Changes

File Path Change Summary
apps/frontend-manage/src/components/analytics/activity/LevelTag.tsx Renamed ActivityLevelTag to LevelTag, updated function signature and translation keys
apps/frontend-manage/src/components/analytics/activity/TotalStudentActivityPlot.tsx Updated import and usage of LevelTag component
apps/frontend-manage/src/components/analytics/activity/useTotalStudentActivityHistogram.ts Renamed groupHistogramBins to groupStudentActivityBins, imported new statistics computation method
apps/frontend-manage/src/components/analytics/computeHistogramStatistics.ts Added new function to compute histogram statistics
apps/frontend-manage/src/components/analytics/performance/TotalStudentPerformancePlot.tsx New component for visualizing student performance data
apps/frontend-manage/src/components/analytics/performance/useTotalStudentPerformanceHistogram.ts New custom hook for computing performance histogram
apps/frontend-manage/src/pages/analytics/[courseId]/performance.tsx Added TotalStudentPerformancePlot to performance dashboard
packages/graphql/src/graphql/ops/QGetCoursePerformanceAnalytics.graphql Added participantPerformances field to query
packages/graphql/src/schema/analytics.ts Added new types for performance levels and participant performance
packages/graphql/src/services/analytics.ts Updated performance analytics service to include participant performance
packages/i18n/messages/de.ts Updated translation keys for activity levels
packages/i18n/messages/en.ts Updated translation keys for activity levels
packages/types/src/index.ts Added new ParticipantPerformance type

Possibly related PRs


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (10)
packages/graphql/src/ops.ts (2)

1990-1999: LGTM! Consider adding field descriptions.

The ParticipantPerformance type is well-structured with comprehensive performance tracking. Consider adding GraphQL descriptions to document the meaning of each field, especially the difference between first, last, and total metrics.

Example documentation:

 export type ParticipantPerformance = {
   __typename?: 'ParticipantPerformance';
+  /** Error rate from the first attempt */
   firstErrorRate: Scalars['Float']['output'];
+  /** Performance level achieved in the first attempt */
   firstPerformance: PerformanceLevel;
   id: Scalars['Int']['output'];
+  /** Error rate from the most recent attempt */
   lastErrorRate: Scalars['Float']['output'];
+  /** Performance level achieved in the most recent attempt */
   lastPerformance: PerformanceLevel;
+  /** Aggregate error rate across all attempts */
   totalErrorRate: Scalars['Float']['output'];
+  /** Overall performance level considering all attempts */
   totalPerformance: PerformanceLevel;
 };

2023-2027: Consider reordering enum values.

The PerformanceLevel enum values should follow a logical order from lowest to highest for better readability and maintainability.

 export enum PerformanceLevel {
-  High = 'HIGH',
-  Low = 'LOW',
-  Medium = 'MEDIUM'
+  Low = 'LOW',
+  Medium = 'MEDIUM',
+  High = 'HIGH'
 }
apps/frontend-manage/src/components/analytics/performance/TotalStudentPerformancePlot.tsx (2)

79-107: **Reference lines: labeling approach **
The labeling of Q1, Q3, median, and mean is handled well. However, consider adding a more descriptive label or tooltip entry about the significance of these lines for users unfamiliar with these statistical markers.


111-187: **Data table usage and structure **
The data table columns are concise and well-labeled. As a future improvement, consider extracting repetitive sorting button logic into a helper component for improved readability and minimizing repeated boilerplate code within each column.

apps/frontend-manage/src/components/analytics/performance/useTotalStudentPerformanceHistogram.ts (1)

20-33: **Color-coding logic **
The approach for color selection (conditions for Q1, Q3, mean, etc.) is clear. For better maintainability, you could define these colors in a central configuration or theme object instead of inline.

packages/graphql/src/schema/analytics.ts (1)

213-232: Consider adding documentation for performance metrics

The ParticipantPerformance type is well-structured but would benefit from documentation explaining:

  • The meaning of each error rate
  • How performance levels are calculated
  • The differences between first, last, and total metrics
packages/types/src/index.ts (1)

398-406: Consider adding JSDoc comments for type documentation

While the type definition is correct, adding JSDoc comments would improve code maintainability by documenting:

  • The purpose of the type
  • The meaning of each field
  • The relationship between error rates and performance levels

Example:

+/**
+ * Represents a participant's performance metrics in a course
+ * @property firstErrorRate - Error rate from first attempts
+ * @property firstPerformance - Performance level based on first attempts
+ * @property lastErrorRate - Error rate from most recent attempts
+ * @property lastPerformance - Performance level based on recent attempts
+ * @property totalErrorRate - Overall error rate across all attempts
+ * @property totalPerformance - Overall performance level
+ */
export type ParticipantPerformance = {
  id: number
  firstErrorRate: number
  firstPerformance: PerformanceLevel
  lastErrorRate: number
  lastPerformance: PerformanceLevel
  totalErrorRate: number
  totalPerformance: PerformanceLevel
}
packages/graphql/src/public/schema.graphql (1)

1256-1260: Consider adding descriptions to enum values

While the enum is correctly defined, adding descriptions would improve API documentation.

Example:

"""
Represents the performance level of a participant
"""
enum PerformanceLevel {
  "Indicates high performance with low error rates"
  HIGH
  "Indicates low performance with high error rates"
  LOW
  "Indicates moderate performance with average error rates"
  MEDIUM
}
packages/graphql/src/public/server.json (1)

121-121: LGTM! Consider documenting the performance metrics.

The addition of participantPerformances field enhances the analytics capabilities by providing individual student performance tracking. This aligns well with the PR objectives.

Consider documenting the meaning and calculation method of each performance metric (errorRate, performance) to help frontend developers properly visualize these values.

packages/graphql/src/ops.schema.json (1)

18186-18309: LGTM! Well-structured performance tracking type.

The ParticipantPerformance type provides a comprehensive structure for tracking individual student performance metrics, with clear separation between first attempt, last attempt, and total performance indicators.

Consider adding the following in future iterations:

  • Timestamp fields to track when performance metrics were last updated
  • Aggregated statistics like average attempts per question
  • Progress tracking fields to show improvement over time
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dd3014f and d7e7ea7.

📒 Files selected for processing (18)
  • apps/frontend-manage/src/components/analytics/activity/LevelTag.tsx (1 hunks)
  • apps/frontend-manage/src/components/analytics/activity/TotalStudentActivityPlot.tsx (2 hunks)
  • apps/frontend-manage/src/components/analytics/activity/useTotalStudentActivityHistogram.ts (2 hunks)
  • apps/frontend-manage/src/components/analytics/computeHistogramStatistics.ts (1 hunks)
  • apps/frontend-manage/src/components/analytics/performance/TotalStudentPerformancePlot.tsx (1 hunks)
  • apps/frontend-manage/src/components/analytics/performance/useTotalStudentPerformanceHistogram.ts (1 hunks)
  • apps/frontend-manage/src/pages/analytics/[courseId]/performance.tsx (2 hunks)
  • packages/graphql/src/graphql/ops/QGetCoursePerformanceAnalytics.graphql (1 hunks)
  • packages/graphql/src/ops.schema.json (3 hunks)
  • packages/graphql/src/ops.ts (5 hunks)
  • packages/graphql/src/public/client.json (1 hunks)
  • packages/graphql/src/public/schema.graphql (3 hunks)
  • packages/graphql/src/public/server.json (1 hunks)
  • packages/graphql/src/schema/analytics.ts (4 hunks)
  • packages/graphql/src/services/analytics.ts (2 hunks)
  • packages/i18n/messages/de.ts (2 hunks)
  • packages/i18n/messages/en.ts (2 hunks)
  • packages/types/src/index.ts (2 hunks)
🔥 Files not summarized due to errors (1)
  • packages/graphql/src/ops.ts: Error: Server error: no LLM provider could handle the message
✅ Files skipped from review due to trivial changes (1)
  • packages/graphql/src/public/client.json
🧰 Additional context used
🪛 Biome (1.9.4)
apps/frontend-manage/src/components/analytics/performance/TotalStudentPerformancePlot.tsx

[error] 192-192: This code is unreachable

... because this statement will return from the function beforehand

(lint/correctness/noUnreachable)

🔇 Additional comments (26)
apps/frontend-manage/src/components/analytics/activity/LevelTag.tsx (1)

3-27: LGTM! Clean and well-structured component.

The component is well-implemented with:

  • Clear and consistent naming
  • Proper type constraints
  • Efficient conditional rendering
  • Semantic color coding (green/yellow/red)
  • Consistent translation key usage
apps/frontend-manage/src/components/analytics/activity/TotalStudentActivityPlot.tsx (1)

16-16: LGTM! Component updates are consistent.

The changes correctly reflect the component renaming:

  • Import statement updated to LevelTag
  • Prop name updated from activityLevel to level

Also applies to: 163-163

packages/i18n/messages/en.ts (2)

1845-1847: LGTM! Translation keys updated consistently.

The translation keys have been simplified by removing the "activity" prefix while maintaining clear semantics.


1872-1876: LGTM! New analytics translation keys added.

Added translation keys to support the new student performance analytics features:

  • Overall student performance
  • Error rate metrics
  • Performance level indicators
packages/i18n/messages/de.ts (2)

1857-1859: LGTM! Activity level translations are accurate and consistent.

The translations for activity levels (HOCH, MITTEL, TIEF) are appropriate and align with the key renaming from activityLevel to level prefix.


1885-1890: LGTM! Student performance translations are clear and consistent.

The translations for student performance analytics are accurate and maintain consistency with existing analytics-related terminology in the application.

packages/graphql/src/ops.ts (3)

366-366: LGTM! Field addition follows GraphQL conventions.

The new field participantPerformances is correctly typed as a non-nullable array of ParticipantPerformance objects.


3672-3672: LGTM! Comprehensive query type definition.

The GetCoursePerformanceAnalyticsQuery type is well-structured with appropriate nullability constraints and follows GraphQL naming conventions.


4189-4189: LGTM! Verify query performance.

The GraphQL document is well-structured with comprehensive field selections. Consider verifying the query performance with large datasets, as it retrieves detailed performance metrics for multiple entities.

apps/frontend-manage/src/components/analytics/performance/TotalStudentPerformancePlot.tsx (3)

1-4: **Imports look good **
No issues noted; these imports appear to be correctly referencing the defined GraphQL types.


19-25: **Well-defined interface for props **
This interface is straightforward. Consider adding JSDoc annotations if you want extra clarity on the expected shape of participantPerformance and any usage notes.


36-38: **Early return for empty data **
This guard effectively prevents rendering empty charts. Good approach to avoid blank or erroneous displays.

packages/graphql/src/graphql/ops/QGetCoursePerformanceAnalytics.graphql (1)

46-55: **New participantPerformances field **
Exposing detailed performance data under participantPerformances is consistent with the analytics feature. No issues detected with the field definitions.

apps/frontend-manage/src/components/analytics/performance/useTotalStudentPerformanceHistogram.ts (1)

1-3: **Memoization approach **
Using useMemo is a good optimization strategy, as it prevents unnecessary computations for frequently re-rendered components.

apps/frontend-manage/src/components/analytics/activity/useTotalStudentActivityHistogram.ts (2)

3-3: LGTM! Function rename improves clarity

The rename from groupHistogramBins to groupStudentActivityBins better reflects its specific purpose in the student activity context.

Also applies to: 6-6


23-24: Verify statistics computation consistency

The switch to using the external computeHistogramStatistics function looks good, but we should verify that it maintains consistency with the previous implementation.

✅ Verification successful

Statistics computation implementation looks consistent and well-structured

The computeHistogramStatistics function is now centralized in a dedicated file (computeHistogramStatistics.ts) and is being used consistently across both activity and performance histograms. The implementation is clean and handles all necessary statistical calculations (mean, median, Q1, Q3) in a standard way. While we can't directly compare with the previous implementation, the current centralized approach reduces code duplication and ensures consistency.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other usages of computeHistogramStatistics to ensure consistent implementation
ast-grep --pattern 'computeHistogramStatistics($_)'

Length of output: 367


Script:

#!/bin/bash
# Let's find the implementation of computeHistogramStatistics
ast-grep --pattern 'function computeHistogramStatistics($_) {
  $$$
}'

# Also search for any exports of this function
rg "export.*computeHistogramStatistics"

Length of output: 1732


Script:

#!/bin/bash
# Let's find the previous implementation in git history
git log -p apps/frontend-manage/src/components/analytics/activity/useTotalStudentActivityHistogram.ts | grep -A 20 "stats ="

Length of output: 0

apps/frontend-manage/src/pages/analytics/[courseId]/performance.tsx (1)

71-74: LGTM! Performance plot integration

The TotalStudentPerformancePlot is properly integrated into the dashboard with appropriate props from the course data.

packages/graphql/src/services/analytics.ts (2)

144-144: LGTM! Added participant performance data

The inclusion of participantPerformances in the course query enhances the analytics capabilities.


270-270: Verify GraphQL schema compatibility

The addition of participantPerformances to the return object looks good, but we should verify the type definition in the GraphQL schema.

✅ Verification successful

GraphQL schema compatibility verified

The participantPerformances field is properly defined in the GraphQL schema with correct type definitions:

  • Field is defined in CoursePerformanceAnalytics type as participantPerformances: [ParticipantPerformance!]!
  • ParticipantPerformance type is properly defined with all required fields
  • Type definitions are consistent across the codebase in both schema and implementation files
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for participantPerformances type definition in GraphQL schema
rg -A 5 "type.*ParticipantPerformance" --type graphql

Length of output: 87


Script:

#!/bin/bash
# Search for ParticipantPerformance type definition in all files
rg -A 5 "type.*ParticipantPerformance"

# Also search for participantPerformances field definition
rg -A 2 "participantPerformances.*:"

Length of output: 19800

packages/graphql/src/schema/analytics.ts (3)

6-6: LGTM: Import added for new performance type

The import statement correctly references the new type from the shared types package.


20-22: LGTM: New PerformanceLevel enum added

The enum correctly maps the database-level performance levels to the GraphQL schema.


240-240: LGTM: CoursePerformanceAnalytics updated

The type correctly includes the new participantPerformances field, maintaining consistency with the schema design.

Also applies to: 259-261

packages/types/src/index.ts (1)

4-4: LGTM: PerformanceLevel import added

The import correctly references the enum from the Prisma package.

packages/graphql/src/public/schema.graphql (1)

1227-1235: LGTM: ParticipantPerformance type exposed in public schema

The type definition correctly exposes all necessary fields for client consumption.

packages/graphql/src/ops.schema.json (2)

18510-18539: LGTM! Clear and concise performance level enum.

The PerformanceLevel enum provides a simple but effective categorization of performance levels.


3724-3747: LGTM! Well-integrated analytics field.

The participantPerformances field is properly integrated into the CoursePerformanceAnalytics type, maintaining schema consistency and providing access to individual performance data.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/frontend-manage/src/components/analytics/performance/TotalStudentPerformancePlot.tsx (2)

27-39: Consider handling loading state.

While the empty state is handled properly, consider adding a loading state to improve user experience during data processing.

 function TotalStudentPerformancePlot({
   courseName,
   participantPerformance,
 }: TotalStudentPerformancePlotProps) {
   const t = useTranslations()
   const performanceData = useTotalStudentPerformanceHistogram({
     participantPerformance,
   })

+  // Show loading state while data is being processed
+  if (!participantPerformance) {
+    return <div>{t('shared.generic.loading')}</div>
+  }

   if (performanceData.length === 0) {
     return null
   }

40-109: Consider centralizing color management.

The chart uses hardcoded colors for statistical markers. Consider moving these to a theme configuration for better maintainability and consistency.

+ // Create a color constants file (e.g., theme/colors.ts)
+ export const CHART_COLORS = {
+   MEAN: 'red',
+   MEDIAN: 'blue',
+   QUARTILE: '#666',
+ }

  <ReferenceLine
    key={`line-${index}`}
    x={entry.errorRate}
    stroke={
-     entry.isMean ? 'red' : entry.isMedian ? 'blue' : '#666'
+     entry.isMean ? CHART_COLORS.MEAN : entry.isMedian ? CHART_COLORS.MEDIAN : CHART_COLORS.QUARTILE
    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d7e7ea7 and 572c0ff.

📒 Files selected for processing (2)
  • apps/frontend-manage/src/components/analytics/computeHistogramStatistics.ts (1 hunks)
  • apps/frontend-manage/src/components/analytics/performance/TotalStudentPerformancePlot.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/frontend-manage/src/components/analytics/computeHistogramStatistics.ts
🔇 Additional comments (2)
apps/frontend-manage/src/components/analytics/performance/TotalStudentPerformancePlot.tsx (2)

1-25: LGTM! Well-structured imports and interface definition.

The imports are properly organized and the interface is well-typed with clear prop definitions.


193-193: LGTM! Proper export statement.

The component is correctly exported as the default export.

Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
16.8% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

1 participant