Expose submissions: list_submissions, and get_task shows your own
Adds what the API actually permits, which is less than the request asked
for and worth being precise about.
GET /api/v3/submissions/status/task/{taskId} is the only submission
route — no list, no fetch-by-id — so a task id is the only way in. The
probe in the report missed it by trying /api/v3/submissions (404). Its
payload is {id, submitters, isSubmitted, isGraded, grade,
submittingCourseGroupName} and nothing more: no submitted text, no grade
comment, no graded-at. Those lived on /api/v1, which this instance does
not serve at all (404 across the board, confirmed — not the proxy). So
"what feedback did I get" is answerable only when the feedback is a file.
Submitted files are reachable, which covers the main workflow:
get_task now shows the submission id, graded state, grade, group, and
the handed-in files with ids ready for download_file. list_submissions
surveys tasks for "what have I handed in" and "what is still ungraded".
Both state the text/feedback gap rather than implying none was given.
Two things found while building it:
files-storage ignores the parentType path segment when listing —
.../gradings/{id} returns the same records, saying parentType
"submissions". Filtering on each record's own parentType, or a student's
own upload gets reported back as teacher feedback.
get_task could not find this task at all: the task lists only cover the
dashboard, and group-project tasks are absent from both, so it claimed
the id was wrong for a task the account can plainly see. It now falls
back to scanning course pages.
Also bounds live search by measured cost: resolving attachments needs a
request per board element, which is 2s for one course but 325s for all
of them — beyond any client timeout. An unscoped fresh search now reads
text only and says so.
38/38 smoke checks; verified end to end through Claude Code against a
real graded group submission.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import type {
|
||||
MeResponse,
|
||||
NewsResponse,
|
||||
Paginated,
|
||||
SubmissionStatus,
|
||||
TaskContent,
|
||||
} from './types.ts';
|
||||
|
||||
@@ -281,6 +282,22 @@ export class SchulcloudClient {
|
||||
});
|
||||
}
|
||||
|
||||
// --- submissions -----------------------------------------------------
|
||||
|
||||
/**
|
||||
* Submission statuses for one task.
|
||||
*
|
||||
* The only way to obtain a submission id: there is no `GET /submissions` and
|
||||
* no `GET /submissions/{id}`. What comes back depends on the account — a
|
||||
* student sees their own submission, a teacher sees the whole class's.
|
||||
*/
|
||||
async listSubmissionStatuses(taskId: string): Promise<SubmissionStatus[]> {
|
||||
const page = await this.getJson<{ data: SubmissionStatus[] }>(
|
||||
`/api/v3/submissions/status/task/${encodeURIComponent(taskId)}`,
|
||||
);
|
||||
return page.data ?? [];
|
||||
}
|
||||
|
||||
// --- lessons ---------------------------------------------------------
|
||||
|
||||
getLesson(lessonId: string): Promise<LessonResponse> {
|
||||
|
||||
@@ -218,6 +218,26 @@ export const FILE_PARENT_TYPES: FileParentType[] = [
|
||||
'externaltools',
|
||||
];
|
||||
|
||||
/**
|
||||
* One submission's status for a task.
|
||||
*
|
||||
* This is the entire submission surface the v3 API offers — there is no
|
||||
* endpoint for the submitted *text*, the grade comment, or a graded-at
|
||||
* timestamp, and the legacy `/api/v1` surface that once carried them is not
|
||||
* served on this instance (404, not proxied away). Submitted work that is a
|
||||
* file is still reachable, through files-storage.
|
||||
*/
|
||||
export interface SubmissionStatus {
|
||||
id: string;
|
||||
/** User ids. A group submission lists every member. */
|
||||
submitters: string[];
|
||||
isSubmitted: boolean;
|
||||
isGraded: boolean;
|
||||
/** Present only when a numeric grade was given; often null even if graded. */
|
||||
grade?: number | null;
|
||||
submittingCourseGroupName?: string;
|
||||
}
|
||||
|
||||
export interface DashboardResponse {
|
||||
id: string;
|
||||
gridElements: {
|
||||
|
||||
Reference in New Issue
Block a user