Skip to content

feat: dashboard for research experiments#2278

Merged
jo-elimu merged 2 commits intomainfrom
2260-dashboard-research-experiments
Jun 21, 2025
Merged

feat: dashboard for research experiments#2278
jo-elimu merged 2 commits intomainfrom
2260-dashboard-research-experiments

Conversation

@jo-elimu
Copy link
Copy Markdown
Member

@jo-elimu jo-elimu commented Jun 21, 2025

image

Issue Number

Purpose

Technical Details

Testing Instructions

Screenshots


Format Checks

Note

Files in PRs are automatically checked for format violations with mvn spotless:check.

If this PR contains files with format violations, run mvn spotless:apply to fix them.

@jo-elimu jo-elimu self-assigned this Jun 21, 2025
@jo-elimu jo-elimu requested a review from a team as a code owner June 21, 2025 17:07
@jo-elimu jo-elimu requested review from SnehaHS65, Souvik-Cyclic and vrudas and removed request for a team June 21, 2025 17:07
@jo-elimu jo-elimu linked an issue Jun 21, 2025 that may be closed by this pull request
@codecov
Copy link
Copy Markdown

codecov bot commented Jun 21, 2025

Codecov Report

Attention: Patch coverage is 1.16959% with 169 lines in your changes missing coverage. Please review.

Project coverage is 16.33%. Comparing base (fc5e4b7) to head (7d32b2d).
Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
...ics/research/experiments/ExperimentController.java 0.96% 103 Missing ⚠️
.../ai/elimu/web/servlet/CustomDispatcherServlet.java 0.00% 31 Missing ⚠️
...limu/dao/jpa/LetterSoundAssessmentEventDaoJpa.java 0.00% 4 Missing ⚠️
.../elimu/dao/jpa/LetterSoundLearningEventDaoJpa.java 0.00% 4 Missing ⚠️
...va/ai/elimu/dao/jpa/NumberLearningEventDaoJpa.java 0.00% 4 Missing ⚠️
...ai/elimu/dao/jpa/StoryBookLearningEventDaoJpa.java 0.00% 4 Missing ⚠️
...ava/ai/elimu/dao/jpa/VideoLearningEventDaoJpa.java 0.00% 4 Missing ⚠️
...va/ai/elimu/dao/jpa/WordAssessmentEventDaoJpa.java 0.00% 4 Missing ⚠️
...java/ai/elimu/dao/jpa/WordLearningEventDaoJpa.java 0.00% 4 Missing ⚠️
...ava/ai/elimu/dao/jpa/StoryBookParagraphDaoJpa.java 0.00% 3 Missing ⚠️
... and 2 more
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #2278      +/-   ##
============================================
- Coverage     16.68%   16.33%   -0.36%     
- Complexity      448      450       +2     
============================================
  Files           252      254       +2     
  Lines          7372     7543     +171     
  Branches        845      857      +12     
============================================
+ Hits           1230     1232       +2     
- Misses         6077     6246     +169     
  Partials         65       65              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jun 21, 2025

Caution

Review failed

The pull request is closed.

"""

Walkthrough

This change introduces research experiment analytics functionality. It adds new DAO methods and JPA implementations to filter learning and assessment events by research experiment and experiment group. New controllers and JSP pages provide listing and detailed comparison of research experiments. The database population and test code are updated to use the new enum values and fields.

Changes

File(s) Change Summary
pom-dependency-tree.txt Updated dependency versions for ai.elimu:webapp and ai.elimu:model.
.../dao/*EventDao.java Added readAll(ResearchExperiment, ExperimentGroup) method to each DAO interface for event filtering.
.../dao/StoryBookParagraphDao.java Added readAll(StoryBook) method to interface.
.../dao/jpa/*EventDaoJpa.java Implemented readAll(ResearchExperiment, ExperimentGroup) in each JPA DAO for event filtering.
.../dao/jpa/StoryBookParagraphDaoJpa.java Implemented readAll(StoryBook) method to query paragraphs by storybook.
.../web/analytics/MainAnalyticsController.java Added researchExperimentCount model attribute.
.../web/analytics/research/experiments/ExperimentController.java New controller for displaying research experiment analytics by experiment and group.
.../web/analytics/research/experiments/ExperimentListController.java New controller for listing all research experiments.
.../web/servlet/CustomDispatcherServlet.java Set researchExperiment and random experimentGroup on generated event entities in database population.
.../webapp/WEB-INF/jsp/analytics/main.jsp Added "Research Experiments" card with count and link to experiments list.
.../webapp/WEB-INF/jsp/analytics/research/experiments/id.jsp New JSP for displaying detailed analytics for a specific research experiment.
.../webapp/WEB-INF/jsp/analytics/research/experiments/list.jsp New JSP for listing all research experiments and their theories.
.../util/csv/CsvAnalyticsExtractionHelperTest.java Updated assertions to use new ResearchExperiment enum value in tests.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ExperimentListController
    participant Model
    participant View

    User->>ExperimentListController: GET /analytics/research/experiments
    ExperimentListController->>Model: Add researchExperiments
    ExperimentListController->>View: Return "analytics/research/experiments/list"
Loading
sequenceDiagram
    participant User
    participant ExperimentController
    participant DAOs
    participant Model
    participant View

    User->>ExperimentController: GET /analytics/research/experiments/{researchExperiment}
    ExperimentController->>DAOs: readAll(researchExperiment, CONTROL/TREATMENT)
    DAOs-->>ExperimentController: Event lists by group
    ExperimentController->>Model: Add event lists to model
    ExperimentController->>View: Return "analytics/research/experiments/id"
Loading

Assessment against linked issues

Objective Addressed Explanation
Add research experiments analytics and comparison by control/treatment group (#2260)
Provide /analytics/research/<ResearchExperiment> endpoint and UI for comparing learning outcomes (#2260)
Enable filtering of event data by research experiment and experiment group (#2260)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.

Possibly related PRs

Suggested reviewers

  • vrudas
  • Souvik-Cyclic
  • nya-elimu
    """

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f5832e7 and 7d32b2d.

📒 Files selected for processing (5)
  • src/main/java/ai/elimu/dao/StoryBookParagraphDao.java (1 hunks)
  • src/main/java/ai/elimu/dao/jpa/StoryBookParagraphDaoJpa.java (2 hunks)
  • src/main/java/ai/elimu/web/analytics/research/experiments/ExperimentController.java (1 hunks)
  • src/main/java/ai/elimu/web/servlet/CustomDispatcherServlet.java (12 hunks)
  • src/main/webapp/WEB-INF/jsp/analytics/research/experiments/id.jsp (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this 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
Copy Markdown
Contributor

@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: 3

🔭 Outside diff range comments (2)
src/main/webapp/WEB-INF/jsp/analytics/research/experiments/list.jsp (1)

1-32: Enhance security and add missing taglib declarations.

The JSP structure is well-organized, but consider these improvements:

  1. Missing taglib declarations: Add the required taglib imports at the top of the file
  2. XSS prevention: Use <c:out> tags to escape output values
  3. Null safety: Add checks for empty experiment lists

Add these improvements to the JSP:

+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
+<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
+<%@ taglib prefix="content" tagdir="/WEB-INF/tags" %>
+
content:title>
    Research Experiments (${fn:length(researchExperiments)})
</content:title>

<content:section cssId="experimentListPage">
    <div class="row">
        <h5><content:gettitle /></h5>
    </div>
+   <c:choose>
+       <c:when test="${not empty researchExperiments}">
    <div class="row">
        <table class="bordered highlight">
            <thead>
                <th>Experiment ID</th>
                <th>Theory</th>
            </thead>
            <tbody>
                <c:forEach var="researchExperiment" items="${researchExperiments}">
                    <tr class="experiment">
                        <td>
                            <a class="experimentLink" href="<spring:url value='/analytics/research/experiments/${researchExperiment}' />">
-                               <code>${researchExperiment}</code>
+                               <code><c:out value="${researchExperiment}" /></code>
                            </a>
                        </td>
                        <td>
-                           <blockquote>${researchExperiment.theory}</blockquote>
+                           <blockquote><c:out value="${researchExperiment.theory}" /></blockquote>
                        </td>
                    </tr>
                </c:forEach>
            </tbody>
        </table>
    </div>
+       </c:when>
+       <c:otherwise>
+           <div class="row">
+               <p>No research experiments found.</p>
+           </div>
+       </c:otherwise>
+   </c:choose>
</content:section>
src/main/java/ai/elimu/dao/jpa/NumberLearningEventDaoJpa.java (1)

26-26: Fix critical typo in parameter name.

There's a typo in the parameter name that will cause a runtime exception when this method is called.

-                .setParameter("androidIdevent", androidId)
+                .setParameter("androidId", androidId)
🧹 Nitpick comments (2)
src/main/webapp/WEB-INF/jsp/analytics/research/experiments/id.jsp (1)

30-30: Fix: Inconsistent HTML structure between CONTROL and TREATMENT progress bars.

CONTROL groups use <div class="progress"> while TREATMENT groups use <span class="progress">. This inconsistency may cause styling issues.

-<span class="progress">
+<div class="progress">

Also applies to: 45-45, 61-61, 76-76, 92-92, 107-107, 123-123, 139-139

src/main/java/ai/elimu/web/analytics/research/experiments/ExperimentController.java (1)

47-69: Suggest: Refactor repetitive DAO calls into a helper method.

The controller has repetitive patterns for fetching CONTROL and TREATMENT data. Consider creating a helper method to reduce code duplication.

Example refactor:

private <T> void addExperimentGroupData(Model model, String eventType, 
    Function<ExperimentGroup, List<T>> daoCall) {
    model.addAttribute(eventType + "_CONTROL", daoCall.apply(ExperimentGroup.CONTROL));
    model.addAttribute(eventType + "_TREATMENT", daoCall.apply(ExperimentGroup.TREATMENT));
}

// Usage:
addExperimentGroupData(model, "letterSoundAssessmentEvents", 
    group -> letterSoundAssessmentEventDao.readAll(researchExperiment, group));
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f3ad32f and f5832e7.

⛔ Files ignored due to path filters (1)
  • pom.xml is excluded by !**/*.xml
📒 Files selected for processing (23)
  • pom-dependency-tree.txt (1 hunks)
  • src/main/java/ai/elimu/dao/LetterSoundAssessmentEventDao.java (1 hunks)
  • src/main/java/ai/elimu/dao/LetterSoundLearningEventDao.java (1 hunks)
  • src/main/java/ai/elimu/dao/NumberLearningEventDao.java (1 hunks)
  • src/main/java/ai/elimu/dao/StoryBookLearningEventDao.java (2 hunks)
  • src/main/java/ai/elimu/dao/VideoLearningEventDao.java (2 hunks)
  • src/main/java/ai/elimu/dao/WordAssessmentEventDao.java (1 hunks)
  • src/main/java/ai/elimu/dao/WordLearningEventDao.java (1 hunks)
  • src/main/java/ai/elimu/dao/jpa/LetterSoundAssessmentEventDaoJpa.java (2 hunks)
  • src/main/java/ai/elimu/dao/jpa/LetterSoundLearningEventDaoJpa.java (2 hunks)
  • src/main/java/ai/elimu/dao/jpa/NumberLearningEventDaoJpa.java (2 hunks)
  • src/main/java/ai/elimu/dao/jpa/StoryBookLearningEventDaoJpa.java (2 hunks)
  • src/main/java/ai/elimu/dao/jpa/VideoLearningEventDaoJpa.java (2 hunks)
  • src/main/java/ai/elimu/dao/jpa/WordAssessmentEventDaoJpa.java (2 hunks)
  • src/main/java/ai/elimu/dao/jpa/WordLearningEventDaoJpa.java (2 hunks)
  • src/main/java/ai/elimu/web/analytics/MainAnalyticsController.java (2 hunks)
  • src/main/java/ai/elimu/web/analytics/research/experiments/ExperimentController.java (1 hunks)
  • src/main/java/ai/elimu/web/analytics/research/experiments/ExperimentListController.java (1 hunks)
  • src/main/java/ai/elimu/web/servlet/CustomDispatcherServlet.java (7 hunks)
  • src/main/webapp/WEB-INF/jsp/analytics/main.jsp (1 hunks)
  • src/main/webapp/WEB-INF/jsp/analytics/research/experiments/id.jsp (1 hunks)
  • src/main/webapp/WEB-INF/jsp/analytics/research/experiments/list.jsp (1 hunks)
  • src/test/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelperTest.java (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (12)
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: build (windows-latest, 17)
  • GitHub Check: build (macos-latest, 21)
  • GitHub Check: build (windows-latest, 21)
  • GitHub Check: build (ubuntu-latest, 21)
  • GitHub Check: test_rest
  • GitHub Check: build (macos-latest, 17)
  • GitHub Check: build (ubuntu-latest, 17)
  • GitHub Check: test_rest
🔇 Additional comments (36)
pom-dependency-tree.txt (1)

1-2: Version bumps look consistent.

The webapp and model version increments align appropriately with the new research experiment features being added.

src/main/java/ai/elimu/web/analytics/MainAnalyticsController.java (2)

11-11: Import statement correctly added.

The ResearchExperiment enum import is properly placed and needed for the new functionality.


44-44: Model attribute implementation follows established patterns.

The research experiment count is correctly calculated using the standard enum values() method and follows the naming convention of existing attributes like studentCount.

src/main/java/ai/elimu/dao/WordAssessmentEventDao.java (2)

9-10: Enum imports correctly added.

The import statements for the research experiment enums are properly added to support the new filtering functionality.


18-18: Method signature follows DAO patterns.

The new readAll method with ResearchExperiment and ExperimentGroup parameters follows established DAO conventions with appropriate return type and exception handling.

src/main/java/ai/elimu/dao/NumberLearningEventDao.java (2)

9-10: Consistent enum imports across DAO interfaces.

The import statements match the pattern established in other DAO interfaces, maintaining consistency across the codebase.


18-18: Method signature maintains consistency with other DAOs.

The readAll method follows the same pattern established in WordAssessmentEventDao, ensuring consistent interface design across different event types.

src/main/webapp/WEB-INF/jsp/analytics/main.jsp (1)

19-28: Research experiments card follows established UI patterns.

The new card structure maintains consistency with the existing Students card design, uses appropriate Material Icons, and correctly references the model attribute from the controller.

src/main/java/ai/elimu/dao/LetterSoundAssessmentEventDao.java (2)

9-10: LGTM: Clean import additions for new enum types.

The import statements are properly organized and support the new filtering functionality.


18-18: LGTM: Well-designed method signature for experiment filtering.

The new method signature follows consistent DAO patterns and provides the filtering capability needed for research experiment analytics.

src/test/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelperTest.java (1)

65-65: Verify enum refactoring consistency across the codebase.

The systematic change from ResearchExperiment.WORD_EMOJIS to ResearchExperiment.EXP_0_WORD_EMOJIS is consistent across all test methods, which is good. However, ensure this enum refactoring is applied consistently throughout the entire codebase to prevent runtime exceptions.

#!/bin/bash
# Description: Verify that the old enum value WORD_EMOJIS is not used anywhere else in the codebase
# Expected: No occurrences of the old enum value should be found

echo "Searching for any remaining usage of the old enum value..."
rg "WORD_EMOJIS" --type java

echo "Searching for the new enum value to confirm it exists..."
rg "EXP_0_WORD_EMOJIS" --type java -A 2 -B 2

Also applies to: 140-140, 187-187, 278-278, 326-326

src/main/java/ai/elimu/dao/VideoLearningEventDao.java (2)

5-6: LGTM: Consistent import organization.

The new enum imports are properly placed and support the extended functionality.


21-21: LGTM: Method signature maintains DAO consistency.

The new readAll method follows the same pattern established in other DAO interfaces, ensuring consistency across the data access layer.

src/main/java/ai/elimu/dao/WordLearningEventDao.java (2)

9-10: LGTM: Proper import organization.

The enum imports are correctly placed and maintain the file's organization.


18-18: LGTM: Consistent method signature.

The new filtering method maintains the established pattern across all DAO interfaces in this PR.

src/main/java/ai/elimu/dao/LetterSoundLearningEventDao.java (1)

9-11: LGTM: Clean interface extension for research experiment filtering.

The new imports and method signature are well-structured and follow consistent DAO patterns. The method signature properly declares the expected parameters and exception handling.

src/main/java/ai/elimu/dao/jpa/NumberLearningEventDaoJpa.java (2)

5-6: LGTM: Appropriate imports for new functionality.

The imports are correctly added to support the new research experiment filtering capability.


46-58: LGTM: Well-implemented research experiment filtering method.

The new readAll method implementation is correctly structured with:

  • Proper JPQL query syntax
  • Parameterized queries to prevent SQL injection
  • Consistent parameter binding
  • Appropriate ordering by timestamp
src/main/java/ai/elimu/dao/jpa/StoryBookLearningEventDaoJpa.java (2)

5-6: LGTM: Consistent imports for research experiment functionality.

The imports are appropriately added to support the new filtering capabilities.


54-66: LGTM: Consistent and secure implementation.

The new readAll method implementation follows the established pattern with:

  • Proper JPQL syntax and parameterization
  • Correct parameter binding for security
  • Consistent ordering and return type
  • Appropriate exception handling
src/main/java/ai/elimu/dao/jpa/WordLearningEventDaoJpa.java (2)

5-6: LGTM: Proper imports for enhanced functionality.

The imports correctly support the new research experiment filtering feature.


46-58: LGTM: Secure and consistent query implementation.

The readAll method implementation properly follows established patterns with:

  • Parameterized JPQL query for security
  • Correct parameter binding
  • Consistent timestamp ordering
  • Appropriate exception handling
src/main/java/ai/elimu/dao/jpa/LetterSoundLearningEventDaoJpa.java (2)

10-11: LGTM: Appropriate enum imports added.

The imports correctly support the new research experiment filtering functionality.


46-58: LGTM: Well-implemented filtering method.

The new readAll method implementation is correctly structured with:

  • Secure parameterized JPQL query
  • Proper parameter binding
  • Consistent ordering by timestamp
  • Matching interface signature and exception handling
src/main/java/ai/elimu/dao/jpa/VideoLearningEventDaoJpa.java (2)

6-7: LGTM: Clean import additions.

The imports for the research experiment enums are properly added.


56-68: LGTM: Well-implemented filtering method.

The new readAll method follows the established patterns in the class with proper parameter binding and consistent ordering. The JPQL query structure is clean and efficient.

src/main/java/ai/elimu/web/servlet/CustomDispatcherServlet.java (1)

45-46: LGTM: Clean import additions.

The imports for the research experiment enums are properly added.

src/main/java/ai/elimu/dao/jpa/LetterSoundAssessmentEventDaoJpa.java (2)

10-11: LGTM: Consistent import pattern.

The imports follow the same pattern established in other DAO files.


46-58: LGTM: Consistent DAO implementation.

The implementation follows the established pattern with proper JPQL query structure, named parameters, and consistent ordering. Good consistency across DAO implementations.

src/main/java/ai/elimu/dao/jpa/WordAssessmentEventDaoJpa.java (2)

10-11: LGTM: Consistent import additions.

The imports are consistent with the pattern used across other DAO implementations.


46-58: LGTM: Well-structured and consistent implementation.

The method implementation maintains excellent consistency with other DAO classes, using the same JPQL query pattern and parameter binding approach. This consistency aids maintainability.

src/main/java/ai/elimu/dao/StoryBookLearningEventDao.java (2)

8-9: LGTM: Proper interface imports.

The enum imports are correctly added to support the new method signature.


19-19: LGTM: Clean interface method declaration.

The method signature is well-defined with appropriate parameter types and exception declaration. This aligns perfectly with the implementations seen in the corresponding JPA classes.

src/main/java/ai/elimu/web/analytics/research/experiments/ExperimentListController.java (1)

11-25: LGTM! Clean and simple controller implementation.

The controller follows Spring MVC best practices with appropriate annotations and dependency injection patterns. The logic is straightforward and correct for a list controller.

src/main/java/ai/elimu/web/analytics/research/experiments/ExperimentController.java (2)

20-38: LGTM! Well-structured controller with proper dependency injection.

The controller follows Spring MVC best practices with appropriate annotations, constructor injection, and clear separation of concerns.


32-32: ```shell
#!/bin/bash

Locate ExperimentController.java

EXP_PATH=$(fd ExperimentController.java --type f)
echo "ExperimentController.java file path: $EXP_PATH"

echo "----- Lines with NumberAssessmentEventDao -----"
grep -n "NumberAssessmentEventDao" "$EXP_PATH" || echo "No occurrences in the controller."

echo "----- model.addAttribute calls in ExperimentController -----"
grep -n "model.addAttribute" "$EXP_PATH"

echo "----- JSP files containing 'Number assessment events' -----"
rg -n "Number assessment events"


</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment thread src/main/java/ai/elimu/web/servlet/CustomDispatcherServlet.java
Comment thread src/main/webapp/WEB-INF/jsp/analytics/research/experiments/id.jsp
Comment thread src/main/webapp/WEB-INF/jsp/analytics/research/experiments/id.jsp
@jo-elimu jo-elimu merged commit 108496c into main Jun 21, 2025
13 checks passed
@jo-elimu jo-elimu deleted the 2260-dashboard-research-experiments branch June 21, 2025 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add research experiments

1 participant