Skip to content

Conversation

@st-manu
Copy link
Contributor

@st-manu st-manu commented Nov 12, 2025

See https://sakaiproject.atlassian.net/browse/SAK-52155

Summary by CodeRabbit

Release Notes

  • New Features
    • Auto-submit functionality for draft assignments after due dates
    • Visual indicators identifying auto-submitted submissions across all assignment views
    • Student warnings for assignments with auto-submit enabled
    • Error notification emails for failed auto-submissions
    • Configurable system settings to enable/disable auto-submit feature and error notifications
    • Instructor checkbox to enable auto-submit per assignment

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 12, 2025

Walkthrough

This PR introduces an auto-submit feature for draft assignments. It adds API methods to retrieve auto-submit assignments and eligible draft submissions, implements a Quartz job for automatic submission processing, extends the instructor UI with an auto-submit checkbox, displays auto-submission indicators throughout the grading and viewing interfaces, and includes configuration properties and email notification templates.

Changes

Cohort / File(s) Summary
API Constants & Contracts
assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentConstants.java, assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentService.java, assignment/api/src/java/org/sakaiproject/assignment/api/persistence/AssignmentRepository.java
Added public constants for auto-submit feature configuration keys and property names; defined three new service methods: getAutoSubmitAssignmentsForContext(), getDraftSubmissionsForAssignment(), getAllEligibleDraftSubmissions(); introduced two inner DTOs: SimpleAssignmentAutoSubmit and SimpleSubmissionDraft.
Service & Repository Implementation
assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentServiceImpl.java, assignment/impl/src/java/org/sakaiproject/assignment/impl/persistence/AssignmentRepositoryImpl.java
Implemented three service methods delegating to repository with input validation; added three repository methods with Hibernate queries to retrieve auto-submit assignments filtered by site and close date, draft submissions by assignment, and all eligible drafts across assignments.
Auto-submit Job & Tests
assignment/impl/src/java/org/sakaiproject/assignment/impl/AutoSubmitAssignmentsJob.java, assignment/impl/src/test/org/sakaiproject/assignment/impl/AutoSubmitAssignmentsJobTest.java
Implemented Quartz job class for batch processing and auto-submitting eligible drafts with error isolation, session/user context management, event posting, and email failure notifications; added comprehensive unit tests covering enabled/disabled states, batch processing, content review integration, and failure scenarios.
Spring Configuration
assignment/impl/src/webapp/WEB-INF/components.xml
Registered AutoSubmitAssignmentsJob bean with dependency injection and scheduled it via SpringJobBeanWrapper.
Properties & Email Templates
assignment/api/src/resources/assignment.properties, assignment/api/src/resources/templates/template-assignmentAutoSubmitErrors.xml, samigo/samigo-pack/src/bundle/template-assessmentAutoSubmitErrors.xml, config/configuration/bundles/src/bundle/org/sakaiproject/config/bundle/default.sakai.properties
Added localization keys for auto-submit UI (checkbox label, description, warning, indicator); created XML email template for auto-submit job failure notifications; added Sakai configuration properties for enabling auto-submit, error notifications, and related settings.
Instructor Assignment Management UI
assignment/tool/src/java/org/sakaiproject/assignment/tool/AssignmentAction.java, assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_new_edit_assignment.vm
Added form state handling for auto-submit checkbox in assignment creation/editing; integrated checkbox input into the instructor new/edit assignment form with label and description, reading from configuration defaults.
Grading & Submission Views
assignment/tool/src/java/org/sakaiproject/assignment/entityproviders/AssignmentEntityProvider.java, assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_grading_submission.vm, assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_submissions.vm, assignment/tool/src/webapp/vm/assignment/chef_assignments_list_assignments.vm, assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_grade.vm, assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_submission.vm
Added autoSubmitted property mapping in entity provider; rendered auto-submit indicator badges in grading submission, submission list, assignment list, and student view pages; added auto-submit warning message in student submission view.
Grader Webcomponents
webcomponents/bundle/src/main/bundle/grader.properties, webcomponents/tool/src/main/frontend/packages/sakai-grader/src/sakai-grader-rendering-mixin.js, webcomponents/tool/src/main/frontend/packages/sakai-grader/src/submission.js
Added localization property for auto-submit indicator text; implemented auto-submit badge rendering in grader top bar when submission is auto-submitted; added autoSubmitted boolean property to Submission model.
Documentation
assignment/docs/auto_submit/README.autoSubmit.txt
Added comprehensive documentation covering feature purpose, configuration, scheduling, workflow, scope limitations, and event logging expectations.

Possibly related PRs

  • sakaiproject/sakai#14055 — Modifies checkbox state handling in AssignmentAction.java for form re-rendering, overlapping with auto-submit checkbox logic.
  • sakaiproject/sakai#13968 — Updates AssignmentAction.java field persistence for draft submissions, related to draft handling in this PR.
  • sakaiproject/sakai#14098 — Modifies AssignmentAction.java parameter and form handling, overlapping with auto-submit parameter initialization and persistence.

Suggested reviewers

  • ern
  • ottenhoff
  • jesusmmp

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.24% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding a Quartz job for auto-submitting assignments. It accurately reflects the core feature introduced across all modified files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.39.9)
assignment/tool/src/java/org/sakaiproject/assignment/tool/AssignmentAction.java
assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentServiceImpl.java

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
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: 9

🧹 Nitpick comments (11)
samigo/samigo-pack/src/bundle/template-assessmentAutoSubmitErrors.xml (1)

4-5: Text update is consistent; minor pluralization nit (optional).

LGTM on renaming to “Assessments AutoSubmit …”. If you want cleaner grammar for singular, consider “had to skip ${failureCount} submission(s)” in both plain and HTML bodies.

Example diff:

-        <message>The Assessments AutoSubmit job encountered errors during processing and had to skip ${failureCount} attempts/submissions. The remaining attempts/submissions were processed successfully.
+        <message>The Assessments AutoSubmit job encountered errors during processing and had to skip ${failureCount} submission(s). The remaining submission(s) were processed successfully.
@@
-        <messagehtml>&lt;p&gt;The Assessments AutoSubmit job encountered errors during processing and had to skip ${failureCount} attempts/submissions. The remaining attempts/submissions were processed successfully.&lt;/p&gt;
+        <messagehtml>&lt;p&gt;The Assessments AutoSubmit job encountered errors during processing and had to skip ${failureCount} submission(s). The remaining submission(s) were processed successfully.&lt;/p&gt;

Also applies to: 9-10

webcomponents/tool/src/main/frontend/packages/sakai-grader/src/submission.js (1)

126-128: Be tolerant to boolean/case variants

If upstream ever sends a boolean or different case, this stays robust.

Apply:

-      // Auto-submit indicator
-      this.autoSubmitted = init.autoSubmitted === "true";
+      // Auto-submit indicator
+      this.autoSubmitted = init.autoSubmitted === true
+        || (typeof init.autoSubmitted === "string" && init.autoSubmitted.toLowerCase() === "true");
assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_submission.vm (1)

1096-1112: Null‑safe property check for auto‑submit flag

Calling .equalsIgnoreCase("true") on a possibly missing property can log errors in Velocity. Use constant‑first comparison to be null‑safe.

Apply:

-                                    #if ($!assignment && $assignment.Properties.get("auto_submit_enabled").equalsIgnoreCase("true"))
+                                    #if ($!assignment && "true".equalsIgnoreCase($!assignment.Properties.get("auto_submit_enabled")))
                                         <span class="sak-banner-warn">$tlang.getString("auto.submit.warning.message")</span>
                                     #end

Optional: add role/aria for the banner container for SRs.

-                            <div class="w-100">
-                                <div>
+                            <div class="w-100" role="status" aria-live="polite">
+                                <div>
assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_grading_submission.vm (1)

175-181: Make auto‑submitted indicator check null‑safe

Guard against missing property by using constant‑first compare.

-                    #if ($!submission && $submission.properties.get("auto_submitted").equalsIgnoreCase("true"))
+                    #if ($!submission && "true".equalsIgnoreCase($!submission.properties.get("auto_submitted")))
                         <br/>
                         <span class="badge bg-info" title="$tlang.getString('auto.submit.indicator.label')">
                             <span class="bi bi-clock-history me-1" aria-hidden="true"></span>
                             $tlang.getString("auto.submit.indicator.label")
                         </span>
                     #end
assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_new_edit_assignment.vm (1)

222-237: Minor a11y polish for help text association

Associate the help copy with the checkbox for SRs.

-            <div class="checkbox">
+            <div class="checkbox">
                 <label for="$name_CheckAutoSubmit">
-                    <input id="$name_CheckAutoSubmit" name="$name_CheckAutoSubmit" type="checkbox" value="true"
+                    <input id="$name_CheckAutoSubmit" name="$name_CheckAutoSubmit" type="checkbox" value="true" aria-describedby="auto-submit-help"
                         #if ($!value_CheckAutoSubmit)
                             checked="checked"
                         #end
                     />
                     $tlang.getString("auto.submit.checkbox.label")
                 </label>
-                <p class="text-muted small">
+                <p id="auto-submit-help" class="text-muted small">
                     $tlang.getString("auto.submit.checkbox.description")
                 </p>
             </div>
assignment/api/src/resources/assignment.properties (1)

1346-1351: Align wording with behavior (due or close date)

Copy currently mentions only “due date”, but the job submits after due or accept‑until (close) date. Suggest updating strings.

-auto.submit.checkbox.description=Draft assignments will be automatically submitted after the due date
-auto.submit.warning.message=This assignment will be automatically submitted if left in draft status after the due date
+auto.submit.checkbox.description=Drafts will be automatically submitted after the due or accept‑until date
+auto.submit.warning.message=Drafts will be automatically submitted after the due or accept‑until date if left in draft status
assignment/docs/auto_submit/README.autoSubmit.txt (1)

1-37: Clarify triggers, timezone, and notification

Concise tweaks recommended:

  • Note it triggers after due OR close (“accept until”) date.
  • State times are evaluated in server time zone.
  • Mention failure email template key (asn.assignmentAutoSubmitErrors) is used when errors occur.

Proposed edits:

  • Under LOGIC, add “Times are evaluated using the application server time zone.”
  • Under EVENTS or CONFIGURATION, add a note: “Failures trigger the asn.assignmentAutoSubmitErrors email template (template-assignmentAutoSubmitErrors.xml).”
assignment/api/src/resources/templates/template-assignmentAutoSubmitErrors.xml (1)

1-19: Consider richer context in failure email

If feasible, include variables like server id, job start/end time, and site/assignment ids in the template to aid troubleshooting. This requires passing those values when rendering.

Examples (only if you can supply them from the job):

  • Subject: “Assignment AutoSubmit Failures on ${serverId}”
  • Body: add “Job started at ${jobStart}, ended at ${jobEnd}.”
assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentConstants.java (2)

171-178: Verify template wiring and enhance documentation for clarity.

Template file confirmed at assignment/api/src/resources/templates/template-assignmentAutoSubmitErrors.xml and properly wired in AutoSubmitAssignmentsJob. Enhance the Javadoc block to clarify that:

  • ASSIGNMENT_AUTO_SUBMIT_ENABLED and PROP_SUBMISSION_AUTO_SUBMITTED are assignment/submission-level property flags.

  • EMAIL_TEMPLATE_AUTO_SUBMIT_ERRORS and EMAIL_TEMPLATE_AUTO_SUBMIT_ERRORS_FILE_NAME are email template identifiers.

  • Consider grouping PROP_SUBMISSION_AUTO_SUBMITTED near other submission-level properties for discoverability.


399-420: Use constants in AssignmentAction.java for consistency with AutoSubmitAssignmentsJob.java.

The new constants in AssignmentConstants.java are properly defined with defaults and correctly used in AutoSubmitAssignmentsJob.java (lines 75, 264, 269–270) with appropriate fallbacks. However, AssignmentAction.java (lines 3340, 3341, 3525) reads the same assignment.autoSubmit.enabled property using hardcoded strings instead of the SAK_PROP_AUTO_SUBMIT_ENABLED constant. While these reads include defaults, refactoring them to use the centralized constants would improve maintainability and consistency across the codebase.

Line 3248 uses a different property (assignment.autoSubmit.defaultCheckbox) not currently defined in constants—consider adding it to AssignmentConstants if this becomes part of the standard configuration.

assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentService.java (1)

903-917: Decouple the service API from persistence DTOs.

By returning SimpleAssignmentAutoSubmit / SimpleSubmissionDraft here we leak the repository layer into the public service contract. Any rework of the persistence package will now ripple into callers of AssignmentService. Please promote these DTOs to proper API-level types (e.g., top-level classes under org.sakaiproject.assignment.api) so the service boundary stays clean.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a43b995 and 4261914.

📒 Files selected for processing (24)
  • assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentConstants.java (2 hunks)
  • assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentService.java (2 hunks)
  • assignment/api/src/java/org/sakaiproject/assignment/api/persistence/AssignmentRepository.java (2 hunks)
  • assignment/api/src/resources/assignment.properties (1 hunks)
  • assignment/api/src/resources/templates/template-assignmentAutoSubmitErrors.xml (1 hunks)
  • assignment/docs/auto_submit/README.autoSubmit.txt (1 hunks)
  • assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentServiceImpl.java (1 hunks)
  • assignment/impl/src/java/org/sakaiproject/assignment/impl/AutoSubmitAssignmentsJob.java (1 hunks)
  • assignment/impl/src/java/org/sakaiproject/assignment/impl/persistence/AssignmentRepositoryImpl.java (2 hunks)
  • assignment/impl/src/test/org/sakaiproject/assignment/impl/AutoSubmitAssignmentsJobTest.java (1 hunks)
  • assignment/impl/src/webapp/WEB-INF/components.xml (1 hunks)
  • assignment/tool/src/java/org/sakaiproject/assignment/entityproviders/AssignmentEntityProvider.java (1 hunks)
  • assignment/tool/src/java/org/sakaiproject/assignment/tool/AssignmentAction.java (11 hunks)
  • assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_grading_submission.vm (1 hunks)
  • assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_submissions.vm (1 hunks)
  • assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_new_edit_assignment.vm (1 hunks)
  • assignment/tool/src/webapp/vm/assignment/chef_assignments_list_assignments.vm (1 hunks)
  • assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_grade.vm (1 hunks)
  • assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_submission.vm (1 hunks)
  • config/configuration/bundles/src/bundle/org/sakaiproject/config/bundle/default.sakai.properties (3 hunks)
  • samigo/samigo-pack/src/bundle/template-assessmentAutoSubmitErrors.xml (1 hunks)
  • webcomponents/bundle/src/main/bundle/grader.properties (1 hunks)
  • webcomponents/tool/src/main/frontend/packages/sakai-grader/src/sakai-grader-rendering-mixin.js (1 hunks)
  • webcomponents/tool/src/main/frontend/packages/sakai-grader/src/submission.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/frontend.mdc)

**/*.{js,mjs,cjs}: Use clean, standard modern JavaScript where possible
When making changes to jQuery code, update it to modern JavaScript if the changes are minimal
Prefer ES6+ features (arrow functions, template literals, destructuring, etc.)
Write modular, reusable JavaScript components
Minimize use of global variables and functions

Files:

  • webcomponents/tool/src/main/frontend/packages/sakai-grader/src/sakai-grader-rendering-mixin.js
  • webcomponents/tool/src/main/frontend/packages/sakai-grader/src/submission.js
webcomponents/**/*.js

📄 CodeRabbit inference engine (.cursor/rules/webcomponents-rule.mdc)

webcomponents/**/*.js: Disallow trailing spaces
Use double quotes for string literals (avoid single quotes)
For i18n, do not use an OR (||) fallback to English; use only the i18n property
Do not manipulate dates/times based on the browser timezone; use Sakai portal user timezone and locale
For Lit internal state, prefix non-reflected state properties with an underscore (e.g., _points) and expose getters if external read access is needed; prefer reacting via declarative template bindings over imperative DOM access

Files:

  • webcomponents/tool/src/main/frontend/packages/sakai-grader/src/sakai-grader-rendering-mixin.js
  • webcomponents/tool/src/main/frontend/packages/sakai-grader/src/submission.js
**/*.java

📄 CodeRabbit inference engine (.cursor/rules/logging-rule.mdc)

**/*.java: Use SLF4J parameterized logging (e.g., logger.info("Value is: {}", value)) instead of string concatenation in log statements
Write log messages and code comments in English; never translate log messages

**/*.java: Java: Never use local variable type inference (var). Always declare explicit types.
When proposing or writing Java code, spell out full types in local variable declarations, for-loops, and try-with-resources.
If Java code uses var, replace it with an explicit type.
Review gate: Treat any PR or suggestion containing Java var as non-compliant; require explicit types before merge.

Files:

  • assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentConstants.java
  • assignment/impl/src/java/org/sakaiproject/assignment/impl/persistence/AssignmentRepositoryImpl.java
  • assignment/api/src/java/org/sakaiproject/assignment/api/persistence/AssignmentRepository.java
  • assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentServiceImpl.java
  • assignment/tool/src/java/org/sakaiproject/assignment/entityproviders/AssignmentEntityProvider.java
  • assignment/tool/src/java/org/sakaiproject/assignment/tool/AssignmentAction.java
  • assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentService.java
  • assignment/impl/src/java/org/sakaiproject/assignment/impl/AutoSubmitAssignmentsJob.java
  • assignment/impl/src/test/org/sakaiproject/assignment/impl/AutoSubmitAssignmentsJobTest.java
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: sakaiproject/sakai PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-07T16:11:33.008Z
Learning: Commit messages should follow: <issue key> <component> <brief description> (e.g., SAK-12345 Assignments add option x)
📚 Learning: 2025-10-07T16:11:33.008Z
Learnt from: CR
Repo: sakaiproject/sakai PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-07T16:11:33.008Z
Learning: Applies to webcomponents/tool/src/main/frontend/**/*.js : Define custom elements for Sakai-specific functionality when building Web Components

Applied to files:

  • webcomponents/tool/src/main/frontend/packages/sakai-grader/src/sakai-grader-rendering-mixin.js
📚 Learning: 2025-10-07T15:11:27.298Z
Learnt from: ottenhoff
Repo: sakaiproject/sakai PR: 0
File: :0-0
Timestamp: 2025-10-07T15:11:27.298Z
Learning: In samigo’s Total Scores view (samigo/samigo-app/src/webapp/jsf/evaluation/totalScores.jsp), mailto links were hidden after commit dee05746 (PR #12312, SAK-49674) added a render check requiring email.fromEmailAddress to be non-empty; PR #14154 (SAK-52058) restores visibility by checking only description.email.

Applied to files:

  • samigo/samigo-pack/src/bundle/template-assessmentAutoSubmitErrors.xml
  • config/configuration/bundles/src/bundle/org/sakaiproject/config/bundle/default.sakai.properties
📚 Learning: 2025-10-07T16:11:33.008Z
Learnt from: CR
Repo: sakaiproject/sakai PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-07T16:11:33.008Z
Learning: Commit messages should follow: <issue key> <component> <brief description> (e.g., SAK-12345 Assignments add option x)

Applied to files:

  • config/configuration/bundles/src/bundle/org/sakaiproject/config/bundle/default.sakai.properties
📚 Learning: 2025-10-07T16:11:33.008Z
Learnt from: CR
Repo: sakaiproject/sakai PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-07T16:11:33.008Z
Learning: Applies to **/sakai-notifications.properties : Use sakai-notifications.properties for internationalized PWA installation messages

Applied to files:

  • config/configuration/bundles/src/bundle/org/sakaiproject/config/bundle/default.sakai.properties
  • assignment/api/src/resources/assignment.properties
🧬 Code graph analysis (5)
assignment/impl/src/java/org/sakaiproject/assignment/impl/persistence/AssignmentRepositoryImpl.java (2)
assignment/api/src/java/org/sakaiproject/assignment/api/persistence/AssignmentRepository.java (2)
  • SimpleAssignmentAutoSubmit (121-130)
  • SimpleSubmissionDraft (132-142)
assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentConstants.java (1)
  • AssignmentConstants (31-425)
assignment/tool/src/java/org/sakaiproject/assignment/tool/AssignmentAction.java (1)
assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentConstants.java (1)
  • AssignmentConstants (31-425)
assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentService.java (1)
assignment/api/src/java/org/sakaiproject/assignment/api/persistence/AssignmentRepository.java (2)
  • SimpleAssignmentAutoSubmit (121-130)
  • SimpleSubmissionDraft (132-142)
assignment/impl/src/java/org/sakaiproject/assignment/impl/AutoSubmitAssignmentsJob.java (2)
assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentConstants.java (1)
  • AssignmentConstants (31-425)
assignment/api/src/java/org/sakaiproject/assignment/api/persistence/AssignmentRepository.java (1)
  • SimpleSubmissionDraft (132-142)
assignment/impl/src/test/org/sakaiproject/assignment/impl/AutoSubmitAssignmentsJobTest.java (2)
assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentConstants.java (1)
  • AssignmentConstants (31-425)
assignment/api/src/java/org/sakaiproject/assignment/api/persistence/AssignmentRepository.java (1)
  • SimpleSubmissionDraft (132-142)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: sakai-deploy
🔇 Additional comments (7)
config/configuration/bundles/src/bundle/org/sakaiproject/config/bundle/default.sakai.properties (2)

2084-2084: Formatting only.

Whitespace/comment spacing change is fine.


3344-3360: Verification complete: all referenced files exist and implementation honors the documented cascade.

  • SQL files exist: ./samigo/docs/auto_submit/auto_submit_mysql.sql and auto_submit_oracle.sql
  • README exists: ./samigo/docs/auto_submit/README.autoSubmit.txt
  • Properties are correctly wired in SamigoETSProviderImpl.java (lines 110–116); cascade honored: toAddresssupportAddress (defaults to mail.support, then to fromAddress) ✓
webcomponents/bundle/src/main/bundle/grader.properties (1)

139-139: LGTM

Key matches webcomponents usage (auto_submit_indicator). No further changes.

webcomponents/tool/src/main/frontend/packages/sakai-grader/src/sakai-grader-rendering-mixin.js (1)

830-835: LGTM

Indicator renders behind a simple boolean; i18n key matches bundle.

assignment/impl/src/webapp/WEB-INF/components.xml (1)

313-332: Bean wiring LGTM; verify scheduler config and concurrency

Wiring and wrapper id look correct. Ensure the scheduled trigger won’t overlap runs; if overlaps are possible, make the job idempotent or configure the scheduler to prevent concurrent executions.

assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentServiceImpl.java (1)

5402-5417: Remove null-safety wrapping suggestions; only minor FQCN consistency issue exists.

The repository methods use Hibernate's criteria API, which guarantees non-null List returns (empty or populated, never null). Wrapping in Optional.ofNullable(...).orElse(List.of()) adds unnecessary complexity without addressing a real null-safety gap. The only valid observation is the inconsistent use of java.time.Instant.now() on line 5405 when Instant is already imported; this could be simplified to Instant.now() for consistency with the import.

Likely an incorrect or invalid review comment.

assignment/impl/src/test/org/sakaiproject/assignment/impl/AutoSubmitAssignmentsJobTest.java (1)

117-137: Nice guardrail for the session lifecycle.

This exercise of the login/start/refresh/logout path makes the Quartz job’s security posture a lot safer against regressions. 👍

Comment on lines +239 to +241
String submitterInfo = String.join(", ", submission.submitterIds != null ? submission.submitterIds : List.of("Unknown"));
eventTrackingService.post(eventTrackingService.newEvent(EVENT_AUTO_SUBMIT_SUBMISSION, "Assignment: " + assignmentEntity.getTitle() + " Submitter: " + submitterInfo, true));
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Clamp event ref to avoid Sakai event truncation errors.

eventTrackingService.newEvent writes into sakai_event.ref, which is capped at 256 chars. For large groups or long titles this concatenated string easily exceeds the limit and will throw during insert, causing the submission to be counted as a failure. Run the value through safeEventLength(...) before posting.

-                    String submitterInfo = String.join(", ", submission.submitterIds != null ? submission.submitterIds : List.of("Unknown"));
-                    eventTrackingService.post(eventTrackingService.newEvent(EVENT_AUTO_SUBMIT_SUBMISSION, "Assignment: " + assignmentEntity.getTitle() + " Submitter: " + submitterInfo, true));
+                    String submitterInfo = String.join(", ", submission.submitterIds != null ? submission.submitterIds : List.of("Unknown"));
+                    String eventRef = safeEventLength("Assignment: " + assignmentEntity.getTitle() + " Submitter: " + submitterInfo);
+                    eventTrackingService.post(eventTrackingService.newEvent(EVENT_AUTO_SUBMIT_SUBMISSION, eventRef, true));

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
assignment/impl/src/java/org/sakaiproject/assignment/impl/AutoSubmitAssignmentsJob.java
around lines 239 to 241, the event detail string passed to
eventTrackingService.newEvent can exceed the 256-char sakai_event.ref limit and
cause DB insert errors; wrap the concatenated detail string in
safeEventLength(...) before calling newEvent (i.e., compute the "Assignment: ...
Submitter: ..." string, pass that through safeEventLength, and use the result as
the event ref when posting) to clamp it to the allowed length.

Comment on lines +301 to +305
UsageSession session = usageSessionService.startSession(whoAs, serverName, "AutoSubmitAssignmentsJob");
if (session == null) {
eventTrackingService.post(eventTrackingService.newEvent(EVENT_AUTO_SUBMIT_JOB_ERROR, whoAs + " unable to log into " + serverName, true));
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Abort job when Sakai login fails.

If usageSessionService.startSession(...) returns null, we log an error but keep going. The next call to sessionManager.getCurrentSession() assumes the session exists and will throw a NullPointerException, aborting the job mid-run. Throw immediately (or return a boolean and bail out) when the login fails so the job exits cleanly instead of crashing later.

         UsageSession session = usageSessionService.startSession(whoAs, serverName, "AutoSubmitAssignmentsJob");
         if (session == null) {
             eventTrackingService.post(eventTrackingService.newEvent(EVENT_AUTO_SUBMIT_JOB_ERROR, whoAs + " unable to log into " + serverName, true));
-            return;
+            throw new IllegalStateException("Unable to start Sakai usage session for " + whoAs);
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
UsageSession session = usageSessionService.startSession(whoAs, serverName, "AutoSubmitAssignmentsJob");
if (session == null) {
eventTrackingService.post(eventTrackingService.newEvent(EVENT_AUTO_SUBMIT_JOB_ERROR, whoAs + " unable to log into " + serverName, true));
return;
}
UsageSession session = usageSessionService.startSession(whoAs, serverName, "AutoSubmitAssignmentsJob");
if (session == null) {
eventTrackingService.post(eventTrackingService.newEvent(EVENT_AUTO_SUBMIT_JOB_ERROR, whoAs + " unable to log into " + serverName, true));
throw new IllegalStateException("Unable to start Sakai usage session for " + whoAs);
}
🤖 Prompt for AI Agents
In
assignment/impl/src/java/org/sakaiproject/assignment/impl/AutoSubmitAssignmentsJob.java
around lines 301 to 305, the code calls usageSessionService.startSession(...)
and then continues even if it returns null; change the control flow so that when
startSession returns null you immediately abort the job (either by returning
from the method or throwing a checked runtime exception) after posting the error
event, ensuring no subsequent call to sessionManager.getCurrentSession() is made
when session is null.

Comment on lines +447 to +487
public List<SimpleSubmissionDraft> findAllEligibleDraftSubmissions() {
// OPTIMIZED QUERY: Get all draft submissions from assignments with auto-submit enabled and past close date
java.time.Instant now = java.time.Instant.now();

List<AssignmentSubmission> submissions = geCurrentSession().createCriteria(AssignmentSubmission.class)
.createAlias("assignment", "a")
.add(Restrictions.eq("submitted", Boolean.FALSE)) // Draft submissions only
.add(Restrictions.eq("a.draft", Boolean.FALSE)) // Published assignments only
.add(Restrictions.eq("a.deleted", Boolean.FALSE)) // Non-deleted assignments only
.add(Restrictions.le("a.closeDate", now)) // Past close date
.list();

return submissions.stream()
.filter(s -> {
// Filter for assignments with auto-submit enabled
String autoSubmit = s.getAssignment().getProperties().get(AssignmentConstants.ASSIGNMENT_AUTO_SUBMIT_ENABLED);
if (!"true".equals(autoSubmit)) {
return false;
}

// Filter for submissions with content (text or attachments)
boolean hasText = s.getSubmittedText() != null && !s.getSubmittedText().trim().isEmpty();
boolean hasAttachments = s.getAttachments() != null && !s.getAttachments().isEmpty();
return hasText || hasAttachments;
})
.map(s -> {
SimpleSubmissionDraft dto = new SimpleSubmissionDraft();
dto.id = s.getId();
dto.gradableId = s.getAssignment().getId();
dto.submitted = Boolean.TRUE.equals(s.getSubmitted());
dto.draft = !Boolean.TRUE.equals(s.getSubmitted());
dto.submittedText = s.getSubmittedText();
dto.attachments = s.getAttachments();
dto.properties = s.getProperties();
dto.submitterIds = s.getSubmitters() != null ?
s.getSubmitters().stream().map(sub -> sub.getSubmitter()).collect(Collectors.toSet()) : null;
dto.dateModified = s.getDateModified();
return dto;
})
.collect(Collectors.toList());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Push the auto-submit filter down into the query.

This "optimized" path still loads every draft submission for every assignment whose close date has passed and only then filters on the auto_submit_enabled property in Java. On a large Sakai install that can be millions of rows pulled into memory each run, defeating the goal of the batch job and risking timeouts. Please add the property restriction to the Hibernate criteria so we only fetch submissions from auto-submit assignments:

List<AssignmentSubmission> submissions = geCurrentSession().createCriteria(AssignmentSubmission.class)
     .createAlias("assignment", "a")
+    .createAlias("a.properties", "props")
+    .add(Restrictions.eq("props." + CollectionPropertyNames.COLLECTION_INDICES,
+         AssignmentConstants.ASSIGNMENT_AUTO_SUBMIT_ENABLED))
+    .add(Restrictions.eq("props." + CollectionPropertyNames.COLLECTION_ELEMENTS, "true"))
     .add(Restrictions.eq("submitted", Boolean.FALSE))
     ...
-        return submissions.stream()
-                .filter(s -> {
-                    String autoSubmit = s.getAssignment().getProperties()
-                            .get(AssignmentConstants.ASSIGNMENT_AUTO_SUBMIT_ENABLED);
-                    if (!"true".equals(autoSubmit)) {
-                        return false;
-                    }
-                    boolean hasText = ...
-                })
+        return submissions.stream()
+                .filter(s -> {
+                    boolean hasText = ...

After that, the stream only needs to enforce the "has text or attachments" rule. This keeps the job scalable.

Comment on lines +854 to +857

// Add auto submit indicator
submission.put("autoSubmitted", as.getProperties().getOrDefault("auto_submitted", "false"));

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Normalize autoSubmitted and use the constant key

Return a canonical "true"/"false" and avoid the string literal to prevent case/typo drift.

Apply:

-            // Add auto submit indicator
-            submission.put("autoSubmitted", as.getProperties().getOrDefault("auto_submitted", "false"));
+            // Add auto submit indicator (normalize to canonical boolean string)
+            submission.put(
+                "autoSubmitted",
+                Boolean.toString(
+                    "true".equalsIgnoreCase(
+                        as.getProperties().getOrDefault(PROP_SUBMISSION_AUTO_SUBMITTED, "false")
+                    )
+                )
+            );

This also leverages the already imported PROP_SUBMISSION_AUTO_SUBMITTED.

🤖 Prompt for AI Agents
In
assignment/tool/src/java/org/sakaiproject/assignment/entityproviders/AssignmentEntityProvider.java
around lines 854 to 857, the code currently puts the raw property value using
the literal "auto_submitted" and may carry case/typo variants; replace that with
a normalized canonical "true"/"false" string and use the existing constant
PROP_SUBMISSION_AUTO_SUBMITTED: read the property via
as.getProperties().get(PROP_SUBMISSION_AUTO_SUBMITTED), convert it to a safe
string (handle null), normalize (e.g., toLowerCase) and set
submission.put("autoSubmitted", value.equals("true") ? "true" : "false").

Comment on lines +3340 to +3343
context.put("allowAutoSubmit", serverConfigurationService.getBoolean("assignment.autoSubmit.enabled", false));
if ((Boolean) serverConfigurationService.getBoolean("assignment.autoSubmit.enabled", false)) {
context.put("name_CheckAutoSubmit", NEW_ASSIGNMENT_CHECK_AUTO_SUBMIT);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix invalid cast to Boolean.

serverConfigurationService.getBoolean(...) returns a primitive boolean, so (Boolean) ... is an illegal cast and the file will not compile. Drop the cast (or wrap with Boolean.valueOf(...)) and reuse the primitive result for both the context value and the conditional. For example:

-        context.put("allowAutoSubmit", serverConfigurationService.getBoolean("assignment.autoSubmit.enabled", false));
-        if ((Boolean) serverConfigurationService.getBoolean("assignment.autoSubmit.enabled", false)) {
+        boolean autoSubmitEnabled = serverConfigurationService.getBoolean("assignment.autoSubmit.enabled", false);
+        context.put("allowAutoSubmit", Boolean.valueOf(autoSubmitEnabled));
+        if (autoSubmitEnabled) {
             context.put("name_CheckAutoSubmit", NEW_ASSIGNMENT_CHECK_AUTO_SUBMIT);
         }
-        if ((Boolean) serverConfigurationService.getBoolean("assignment.autoSubmit.enabled", false)) {
+        if (serverConfigurationService.getBoolean("assignment.autoSubmit.enabled", false)) {
             context.put("value_CheckAutoSubmit", state.getAttribute(NEW_ASSIGNMENT_CHECK_AUTO_SUBMIT));
         }

Also applies to: 3525-3527

🤖 Prompt for AI Agents
In
assignment/tool/src/java/org/sakaiproject/assignment/tool/AssignmentAction.java
around lines 3340-3343 (and likewise at 3525-3527), the code illegally casts the
primitive result of serverConfigurationService.getBoolean(...) to Boolean;
remove the cast and call getBoolean once into a primitive boolean local (e.g.,
boolean allowAutoSubmit = serverConfigurationService.getBoolean(...)) then put
that value into the context and use the primitive in the if check (or wrap with
Boolean.valueOf(...) if an object is strictly required), avoiding the invalid
cast and duplicate calls.

Comment on lines +540 to +546
#if ($!submission && $submission.properties.get("auto_submitted").equalsIgnoreCase("true"))
<br/>
<span class="badge bg-info" title="$tlang.getString('auto.submit.indicator.label')">
<span class="bi bi-clock-history me-1" aria-hidden="true"></span>
$tlang.getString("auto.submit.indicator.label")
</span>
#end
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Null-guard and align i18n key for auto-submit badge

  • Possible NPE from calling equalsIgnoreCase on a null property.
  • The i18n key differs from the webcomponents key and is likely missing from assignment bundles.

Apply:

-                                #if ($!submission && $submission.properties.get("auto_submitted").equalsIgnoreCase("true"))
+                                #set($autoSub = $!submission ? $!submission.properties.get("auto_submitted") : "")
+                                #if ($autoSub && $autoSub.equalsIgnoreCase("true"))
                                     <br/>
-                                    <span class="badge bg-info" title="$tlang.getString('auto.submit.indicator.label')">
+                                    <span class="badge bg-info" title="$tlang.getString('auto_submit_indicator')">
                                         <span class="bi bi-clock-history me-1" aria-hidden="true"></span>
-                                        $tlang.getString("auto.submit.indicator.label")
+                                        $tlang.getString("auto_submit_indicator")
                                     </span>
                                 #end

Add the auto_submit_indicator key to the assignment tool bundles (e.g., assignment.properties, and localized variants):

auto_submit_indicator = Automatically submitted

🏁 Script executed:

#!/bin/bash
# Verify the presence of the auto-submit i18n keys in assignment bundles
rg -n "auto_submit_indicator|auto\.submit\.indicator\.label" -g "assignment/**/src/**/bundle/*.properties" -C2

Length of output: 148


Let me search the codebase more broadly to find the assignment bundle files and verify the i18n key concerns.





---

🏁 Script executed:

```shell
#!/bin/bash
# Find .properties files in assignment-related directories
echo "=== Finding .properties files in assignment directories ==="
fd -e properties "assignment" | head -20

echo -e "\n=== Searching for auto_submit or auto.submit keys anywhere in properties files ==="
rg -n "auto.submit|auto_submit" --type=properties -C2 | head -50

Length of output: 1394


🏁 Script executed:

#!/bin/bash
# Check the actual directory structure
echo "=== Checking assignment directory structure ==="
find . -type d -name "assignment" -o -type d -name "bundles" -o -type d -name "bundle" 2>/dev/null | head -20

echo -e "\n=== Looking for all .properties files ==="
fd -e properties | grep -i "assignment\|bundle" | head -30

Length of output: 2774


🏁 Script executed:

#!/bin/bash
# Search for the webcomponents key mentioned in review
echo "=== Searching for auto_submit_indicator in webcomponents ==="
rg -n "auto_submit_indicator" -C3 | head -30

echo -e "\n=== Searching for where the badge is used or defined ==="
rg -n "auto.submit.indicator.label|auto_submitted" --type=properties -C2 | head -40

Length of output: 1961


Let me search more specifically for these keys in the assignment bundles:





---

🏁 Script executed:

```shell
#!/bin/bash
# Search for auto.submit or auto_submit keys in assignment bundle files
echo "=== Searching for auto.submit or auto_submit keys in assignment.properties ==="
rg -n "auto" assignment/api/src/resources/assignment.properties | head -20

echo -e "\n=== Checking if auto.submit.indicator.label exists anywhere ==="
rg -n "auto.submit.indicator.label" . | head -20

echo -e "\n=== Checking if auto_submit_indicator exists in assignment bundles ==="
rg -n "auto_submit_indicator" assignment/ | head -20

Length of output: 3712


🏁 Script executed:

#!/bin/bash
# Check how Velocity templates handle null/missing properties
echo "=== Looking for similar null-guard patterns in assignment VMs ==="
rg -n "properties.get\(" assignment/tool/src/webapp/vm/ -C2 | head -40

echo -e "\n=== Checking for $! null-safety operator usage ==="
rg -n '\$!' assignment/tool/src/webapp/vm/assignment/ | head -20

Length of output: 7658


🏁 Script executed:

#!/bin/bash
# Search for where auto_submitted is set or used
echo "=== Searching for auto_submitted property ==="
rg -n "auto_submitted" . --type=java | head -30

echo -e "\n=== Checking grader webcomponent integration ==="
rg -n "autoSubmitted" webcomponents/ -C2 | head -30

Length of output: 1774


Apply null-guard to prevent NPE from chained property access

The condition $submission.properties.get("auto_submitted").equalsIgnoreCase("true") risks a null pointer exception if get() returns null. The Velocity $! operator only suppresses output but does not prevent null errors in chained calls. The i18n key auto.submit.indicator.label already exists in the assignment bundle and is correctly used across all assignment VMs, so no key rename is needed.

Apply:

-								#if ($!submission && $submission.properties.get("auto_submitted").equalsIgnoreCase("true"))
+								#set($autoSub = $!submission ? $!submission.properties.get("auto_submitted") : "")
+								#if ($autoSub && $autoSub.equalsIgnoreCase("true"))
 									<br/>
 									<span class="badge bg-info" title="$tlang.getString('auto.submit.indicator.label')">
 										<span class="bi bi-clock-history me-1" aria-hidden="true"></span>
 										$tlang.getString("auto.submit.indicator.label")
 									</span>
 								#end

Note: The same pattern appears in three other files and should be updated consistently:

  • chef_assignments_instructor_grading_submission.vm (line 175)
  • chef_assignments_student_view_grade.vm (line 102)
  • chef_assignments_list_assignments.vm (line 563)
🤖 Prompt for AI Agents
In
assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_submissions.vm
around lines 540-546, the chained call
$submission.properties.get("auto_submitted").equalsIgnoreCase("true") can NPE if
get(...) returns null; capture the property into a local Velocity variable (e.g.
#set($autoSubmitted = $submission.properties.get("auto_submitted")) ) and guard
the equalsIgnoreCase call by first checking the variable is not null (or compare
safely to the literal), then use the guarded comparison to render the badge;
apply the same change to the three other files mentioned
(chef_assignments_instructor_grading_submission.vm line ~175,
chef_assignments_student_view_grade.vm line ~102,
chef_assignments_list_assignments.vm line ~563) so all instances use a
null-checked local variable before calling equalsIgnoreCase.

Comment on lines +563 to +569
#if ($!submission && $submission.properties.get("auto_submitted").equalsIgnoreCase("true"))
<br/>
<span class="badge bg-info" title="$tlang.getString('auto.submit.indicator.label')">
<span class="bi bi-clock-history me-1" aria-hidden="true"></span>
$tlang.getString("auto.submit.indicator.label")
</span>
#end
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Null-safe check and i18n key alignment for auto-submit badge

Same issues as other templates.

Apply:

-                                    #if ($!submission && $submission.properties.get("auto_submitted").equalsIgnoreCase("true"))
+                                    #set($autoSub = $!submission ? $!submission.properties.get("auto_submitted") : "")
+                                    #if ($autoSub && $autoSub.equalsIgnoreCase("true"))
                                         <br/>
-                                        <span class="badge bg-info" title="$tlang.getString('auto.submit.indicator.label')">
+                                        <span class="badge bg-info" title="$tlang.getString('auto_submit_indicator')">
                                             <span class="bi bi-clock-history me-1" aria-hidden="true"></span>
-                                            $tlang.getString("auto.submit.indicator.label")
+                                            $tlang.getString("auto_submit_indicator")
                                         </span>
                                     #end

Ensure auto_submit_indicator exists in assignment bundles.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In assignment/tool/src/webapp/vm/assignment/chef_assignments_list_assignments.vm
around lines 563 to 569, the template assumes submission is non-null and
directly calls properties.get("auto_submitted").equalsIgnoreCase("true") and
uses the wrong i18n key; change the condition to be null-safe (check submission
and properties and the property value before calling equalsIgnoreCase) and use
the correct i18n key "auto_submit_indicator" instead of
"auto.submit.indicator.label"; also verify that the assignment bundles include
the auto_submit_indicator entry so the i18n lookup resolves.

Comment on lines +102 to +108
#if ($!submission && $submission.properties.get("auto_submitted").equalsIgnoreCase("true"))
<br/>
<span class="badge bg-info" title="$tlang.getString('auto.submit.indicator.label')">
<span class="bi bi-clock-history me-1" aria-hidden="true"></span>
$tlang.getString("auto.submit.indicator.label")
</span>
#end
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Prevent null method call and fix i18n key

Guard against null and standardize the key name.

Apply:

-                    #if ($!submission && $submission.properties.get("auto_submitted").equalsIgnoreCase("true"))
+                    #set($autoSub = $!submission ? $!submission.properties.get("auto_submitted") : "")
+                    #if ($autoSub && $autoSub.equalsIgnoreCase("true"))
                         <br/>
-                        <span class="badge bg-info" title="$tlang.getString('auto.submit.indicator.label')">
+                        <span class="badge bg-info" title="$tlang.getString('auto_submit_indicator')">
                             <span class="bi bi-clock-history me-1" aria-hidden="true"></span>
-                            $tlang.getString("auto.submit.indicator.label")
+                            $tlang.getString("auto_submit_indicator")
                         </span>
                     #end

Remember to add auto_submit_indicator to the assignment tool bundles.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#if ($!submission && $submission.properties.get("auto_submitted").equalsIgnoreCase("true"))
<br/>
<span class="badge bg-info" title="$tlang.getString('auto.submit.indicator.label')">
<span class="bi bi-clock-history me-1" aria-hidden="true"></span>
$tlang.getString("auto.submit.indicator.label")
</span>
#end
#set($autoSub = $!submission ? $!submission.properties.get("auto_submitted") : "")
#if ($autoSub && $autoSub.equalsIgnoreCase("true"))
<br/>
<span class="badge bg-info" title="$tlang.getString('auto_submit_indicator')">
<span class="bi bi-clock-history me-1" aria-hidden="true"></span>
$tlang.getString("auto_submit_indicator")
</span>
#end
🤖 Prompt for AI Agents
In
assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_grade.vm
around lines 102 to 108, avoid calling equalsIgnoreCase on a possibly null
properties value and use the standardized i18n key: first fetch the property
into a local variable (e.g., #set($autoSubmitted =
$submission?.properties?.get("auto_submitted"))) and check it safely (e.g., #if
($autoSubmitted && $autoSubmitted.equalsIgnoreCase("true"))), and change the
i18n lookup to $tlang.getString("auto_submit_indicator"); also add the
"auto_submit_indicator" key to the assignment tool language bundles.

Comment on lines +2104 to +2130
# Auto-submit assignments feature (SAK-?????)
# See assignment/docs/auto_submit/README.autoSubmit.txt for instructions.
# DEFAULT: false
# assignment.autoSubmit.enabled=true

# Auto-submit assignments default checkbox option
# DEFAULT: false (checkbox will be unchecked by default)
# assignment.autoSubmit.defaultCheckbox=true

# Enable or disable email notifications for assignments auto-submit failures
# DEFAULT: false (no emails will be sent by default)
# assignment.email.autoSubmit.errorNotification.enabled=true

# Maximum number of threads to use for auto-submit jobs
# DEFAULT: 8
# assignment.autoSubmit.maxThreadPool=8

# Maximum number of sites to process in a single batch
# DEFAULT: 100
# assignment.autoSubmit.batchSize=100

# Set the address to which auto-submit assignments failure emails will be sent to
# DEFAULT: the current value of the 'mail.support' sakai.property
# DEFAULT: if 'mail.support' is not set, the current value of 'setup.request' sakai.property is used
# DEFAULT: if 'setup.request' is not set, property value falls back to "no-reply@" + serverConfigurationService.getServerName()
# assignment.email.autoSubmit.errorNotification.toAddress=notifyUs@example.com

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Replace JIRA placeholder and verify docs exist.

  • Replace “SAK-?????” with the actual key “SAK-52155”.
  • Keep the README path accurate; verify assignment/docs/auto_submit/README.autoSubmit.txt is present in this PR.

Proposed diff:

-# Auto-submit assignments feature (SAK-?????)
+# Auto-submit assignments feature (SAK-52155)

Optionally, consider renaming “assignment.autoSubmit.defaultCheckbox” to a pattern used elsewhere (e.g., “assignment.autoSubmit.checkbox.default”) for consistency; no change required if code already uses the current key.

Run to verify referenced files/keys:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Check assignment auto-submit docs and job presence
fd -t f -a 'README.autoSubmit.txt' | sed -n '1,120p'
fd -t f -a 'AutoSubmitAssignmentsJob.java' | sed -n '1,120p'
# Confirm properties mentioned here exist only once
rg -n 'assignment\.autoSubmit\.(enabled|defaultCheckbox|maxThreadPool|batchSize)' -C1

Length of output: 5203


Replace JIRA placeholder "SAK-?????" with "SAK-52155".

The README path is correct and the file exists. All properties are confirmed in use throughout the codebase. The optional property naming refactoring (defaultCheckbox → checkbox.default) should be skipped—it would require code changes across multiple files and the current naming is already consistent.

-# Auto-submit assignments feature (SAK-?????)
+# Auto-submit assignments feature (SAK-52155)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Auto-submit assignments feature (SAK-?????)
# See assignment/docs/auto_submit/README.autoSubmit.txt for instructions.
# DEFAULT: false
# assignment.autoSubmit.enabled=true
# Auto-submit assignments default checkbox option
# DEFAULT: false (checkbox will be unchecked by default)
# assignment.autoSubmit.defaultCheckbox=true
# Enable or disable email notifications for assignments auto-submit failures
# DEFAULT: false (no emails will be sent by default)
# assignment.email.autoSubmit.errorNotification.enabled=true
# Maximum number of threads to use for auto-submit jobs
# DEFAULT: 8
# assignment.autoSubmit.maxThreadPool=8
# Maximum number of sites to process in a single batch
# DEFAULT: 100
# assignment.autoSubmit.batchSize=100
# Set the address to which auto-submit assignments failure emails will be sent to
# DEFAULT: the current value of the 'mail.support' sakai.property
# DEFAULT: if 'mail.support' is not set, the current value of 'setup.request' sakai.property is used
# DEFAULT: if 'setup.request' is not set, property value falls back to "no-reply@" + serverConfigurationService.getServerName()
# assignment.email.autoSubmit.errorNotification.toAddress=notifyUs@example.com
# Auto-submit assignments feature (SAK-52155)
# See assignment/docs/auto_submit/README.autoSubmit.txt for instructions.
# DEFAULT: false
# assignment.autoSubmit.enabled=true
# Auto-submit assignments default checkbox option
# DEFAULT: false (checkbox will be unchecked by default)
# assignment.autoSubmit.defaultCheckbox=true
# Enable or disable email notifications for assignments auto-submit failures
# DEFAULT: false (no emails will be sent by default)
# assignment.email.autoSubmit.errorNotification.enabled=true
# Maximum number of threads to use for auto-submit jobs
# DEFAULT: 8
# assignment.autoSubmit.maxThreadPool=8
# Maximum number of sites to process in a single batch
# DEFAULT: 100
# assignment.autoSubmit.batchSize=100
# Set the address to which auto-submit assignments failure emails will be sent to
# DEFAULT: the current value of the 'mail.support' sakai.property
# DEFAULT: if 'mail.support' is not set, the current value of 'setup.request' sakai.property is used
# DEFAULT: if 'setup.request' is not set, property value falls back to "no-reply@" + serverConfigurationService.getServerName()
# assignment.email.autoSubmit.errorNotification.toAddress=notifyUs@example.com
🤖 Prompt for AI Agents
config/configuration/bundles/src/bundle/org/sakaiproject/config/bundle/default.sakai.properties
lines 2104-2130: replace the JIRA placeholder "SAK-?????" in the Auto-submit
assignments comment with "SAK-52155" and leave all other property names and
README path unchanged (do not rename defaultCheckbox to checkbox.default); save
and commit the updated comment-only change.

Comment on lines +392 to +417
public List<SimpleAssignmentAutoSubmit> findAutoSubmitAssignmentsBySite(String siteId, java.time.Instant now) {
List<Assignment> assignments = startCriteriaQuery()
.add(Restrictions.eq("context", siteId))
.add(Restrictions.eq("deleted", Boolean.FALSE))
.add(Restrictions.eq("draft", Boolean.FALSE))
.add(Restrictions.le("closeDate", now))
.list();
return assignments.stream()
.filter(a -> {
String autoSubmit = a.getProperties().get(AssignmentConstants.ASSIGNMENT_AUTO_SUBMIT_ENABLED);
return "true".equals(autoSubmit);
})
.map(a -> {
SimpleAssignmentAutoSubmit dto = new SimpleAssignmentAutoSubmit();
dto.id = a.getId();
dto.title = a.getTitle();
dto.dueTime = a.getDueDate();
dto.closeTime = a.getCloseDate();
dto.context = a.getContext();
dto.draft = a.getDraft();
dto.isGroup = Boolean.TRUE.equals(a.getIsGroup());
dto.properties = a.getProperties();
return dto;
})
.collect(Collectors.toList());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The repository should be about interacting with the DB only, this data object should be in the service.

Copy link
Contributor

@ern ern left a comment

Choose a reason for hiding this comment

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

Remove the unrelated data objects SimpleAssignmentAutoSubmit and SimpleSubmissionDraft from the Repository as they are unrelated to querying the db for data. These classes appear to be adapters and hence they should be created in the service, i.e.

  • repository manage persistent POJO's
  • service contains logic to
    • check permissions
    • create adapter
    • populate data

@st-manu st-manu marked this pull request as draft November 18, 2025 09:41
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.

2 participants