diff --git a/schema.graphql b/schema.graphql
index 2d94a90..e6c4749 100644
--- a/schema.graphql
+++ b/schema.graphql
@@ -616,6 +616,25 @@ extend type Query {
courseRepoOverview(course: String!): [AssignmentRepos!]!
}
+"""
+One streamed item of a course repo overview: a completed assignment as it is
+checked, then a final event with `done: true`. `error` is set (with done) when the
+overview cannot start — e.g. no stored GitLab token.
+"""
+type RepoOverviewEvent {
+ "The assignment just checked (null on the final done event)."
+ assignment: AssignmentRepos
+ "Total number of assignments to check (for a progress count)."
+ total: Int!
+ done: Boolean!
+ error: String
+}
+
+extend type Subscription {
+ "Stream the repo overview of one of the caller's courses assignment by assignment, so the GUI shows progress. Needs a stored GitLab token."
+ courseRepoOverviewProgress(course: String!): RepoOverviewEvent!
+}
+
# ----- scheduling.graphqls -----
"The lifecycle state of a scheduled job. It starts PENDING, is claimed to RUNNING, and ends in exactly one terminal state."
enum JobStatus {
diff --git a/src/lib/gql/gql.ts b/src/lib/gql/gql.ts
index 4235d69..d7b301f 100644
--- a/src/lib/gql/gql.ts
+++ b/src/lib/gql/gql.ts
@@ -18,6 +18,7 @@ type Documents = {
"\n\tsubscription CourseCheckProgress($name: String!) {\n\t\tcourseCheckProgress(name: $name) {\n\t\t\tmessage\n\t\t\tdone\n\t\t\terror\n\t\t\tresult {\n\t\t\t\tcourse\n\t\t\t\terrors\n\t\t\t\tok\n\t\t\t\tstudents {\n\t\t\t\t\tinput\n\t\t\t\t\tstatus\n\t\t\t\t\tmessage\n\t\t\t\t}\n\t\t\t\tgroups {\n\t\t\t\t\tname\n\t\t\t\t\tmembers {\n\t\t\t\t\t\tinput\n\t\t\t\t\t\tstatus\n\t\t\t\t\t\tmessage\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tduplicates {\n\t\t\t\t\tstudent\n\t\t\t\t\tgroups\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n": typeof types.CourseCheckProgressDocument,
"\n\tsubscription RunOp($token: String!, $confirmPhrase: String) {\n\t\trunOp(token: $token, confirmPhrase: $confirmPhrase) {\n\t\t\tlevel\n\t\t\ttext\n\t\t}\n\t}\n": typeof types.RunOpDocument,
"\n\tsubscription AssignmentReportProgress($course: String!, $name: String!) {\n\t\tassignmentReportProgress(course: $course, name: $name) {\n\t\t\tmessage\n\t\t\tdone\n\t\t\terror\n\t\t\treport {\n\t\t\t\tcourse\n\t\t\t\tassignment\n\t\t\t\turl\n\t\t\t\tdescription\n\t\t\t\tgenerated\n\t\t\t\thasReleaseMergeRequest\n\t\t\t\thasReleaseDockerImages\n\t\t\t\tprojects {\n\t\t\t\t\tname\n\t\t\t\t\tactive\n\t\t\t\t\temptyRepo\n\t\t\t\t\tcommits\n\t\t\t\t\tlastActivity\n\t\t\t\t\twebUrl\n\t\t\t\t\topenIssuesCount\n\t\t\t\t\topenMergeRequestsCount\n\t\t\t\t\tmembers {\n\t\t\t\t\t\tname\n\t\t\t\t\t\tusername\n\t\t\t\t\t\twebUrl\n\t\t\t\t\t}\n\t\t\t\t\tlastCommit {\n\t\t\t\t\t\ttitle\n\t\t\t\t\t\tcommitterName\n\t\t\t\t\t\tcommittedDate\n\t\t\t\t\t\twebUrl\n\t\t\t\t\t}\n\t\t\t\t\trelease {\n\t\t\t\t\t\tmergeRequest {\n\t\t\t\t\t\t\tfound\n\t\t\t\t\t\t\twebUrl\n\t\t\t\t\t\t\tpipelineStatus\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdockerImages {\n\t\t\t\t\t\t\tstatus\n\t\t\t\t\t\t\timages {\n\t\t\t\t\t\t\t\twanted\n\t\t\t\t\t\t\t\timage\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n": typeof types.AssignmentReportProgressDocument,
+ "\n\tsubscription CourseRepoOverviewProgress($course: String!) {\n\t\tcourseRepoOverviewProgress(course: $course) {\n\t\t\ttotal\n\t\t\tdone\n\t\t\terror\n\t\t\tassignment {\n\t\t\t\tname\n\t\t\t\tper\n\t\t\t\ttargets\n\t\t\t\texisting\n\t\t\t\tnote\n\t\t\t\trepos {\n\t\t\t\t\tfor\n\t\t\t\t\turl\n\t\t\t\t\texists\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n": typeof types.CourseRepoOverviewProgressDocument,
"\n\t\t\t\tquery Me {\n\t\t\t\t\tme {\n\t\t\t\t\t\temail\n\t\t\t\t\t\tname\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": typeof types.MeDocument,
"\n\t\t\t\tquery ServerInfo {\n\t\t\t\t\tserverInfo {\n\t\t\t\t\t\tversion\n\t\t\t\t\t\tcommit\n\t\t\t\t\t\tdate\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": typeof types.ServerInfoDocument,
"\n\t\t\tmutation CopyAssignment($course: String!, $from: String!, $newName: String!) {\n\t\t\t\tcopyAssignment(course: $course, from: $from, newName: $newName) {\n\t\t\t\t\tname\n\t\t\t\t}\n\t\t\t}\n\t\t": typeof types.CopyAssignmentDocument,
@@ -43,7 +44,6 @@ type Documents = {
"\n\t\t\t\tquery CourseLint($name: String!) {\n\t\t\t\t\tcourseLint(name: $name) {\n\t\t\t\t\t\tpath\n\t\t\t\t\t\tmessage\n\t\t\t\t\t\tseverity\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": typeof types.CourseLintDocument,
"\n\t\t\t\tquery CourseActivity($name: String!) {\n\t\t\t\t\tcourseActivity(course: $name) {\n\t\t\t\t\t\tassignment\n\t\t\t\t\t\top\n\t\t\t\t\t\tstatus\n\t\t\t\t\t\tdetail\n\t\t\t\t\t\tat\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": typeof types.CourseActivityDocument,
"\n\t\t\t\tquery AssignmentEditor($course: String!, $name: String!) {\n\t\t\t\t\tcourse(name: $course) {\n\t\t\t\t\t\tassignmentNames\n\t\t\t\t\t}\n\t\t\t\t\tassignmentSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tgroup\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\tdeprecated\n\t\t\t\t\t\texample\n\t\t\t\t\t\toptions {\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t\tlabel\n\t\t\t\t\t\t\tdescription\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbranchRuleSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\texample\n\t\t\t\t\t}\n\t\t\t\t\tapprovalSettingsSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\texample\n\t\t\t\t\t\toptions {\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t\tlabel\n\t\t\t\t\t\t\tdescription\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tapprovalRuleSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\texample\n\t\t\t\t\t}\n\t\t\t\t\tassignment(course: $course, name: $name) {\n\t\t\t\t\t\tcourse\n\t\t\t\t\t\tname\n\t\t\t\t\t\textends\n\t\t\t\t\t\textendsOptions\n\t\t\t\t\t\tabstract\n\t\t\t\t\t\town {\n\t\t\t\t\t\t\tkey\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresolved\n\t\t\t\t\t\tresolveError\n\t\t\t\t\t}\n\t\t\t\t\tassignmentUrls(course: $course, name: $name) {\n\t\t\t\t\t\tper\n\t\t\t\t\t\tgroupUrl\n\t\t\t\t\t\trepos {\n\t\t\t\t\t\t\tfor\n\t\t\t\t\t\t\turl\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tassignmentActivity(course: $course, name: $name) {\n\t\t\t\t\t\top\n\t\t\t\t\t\tstatus\n\t\t\t\t\t\tdetail\n\t\t\t\t\t\tat\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": typeof types.AssignmentEditorDocument,
- "\n\t\t\t\tquery CourseRepoOverview($course: String!) {\n\t\t\t\t\tcourseRepoOverview(course: $course) {\n\t\t\t\t\t\tname\n\t\t\t\t\t\tper\n\t\t\t\t\t\ttargets\n\t\t\t\t\t\texisting\n\t\t\t\t\t\tnote\n\t\t\t\t\t\trepos {\n\t\t\t\t\t\t\tfor\n\t\t\t\t\t\t\turl\n\t\t\t\t\t\t\texists\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": typeof types.CourseRepoOverviewDocument,
"\n\t\t\t\tquery CourseStudents($course: String!) {\n\t\t\t\t\tcourseStudents(course: $course) {\n\t\t\t\t\t\temail\n\t\t\t\t\t\tfound\n\t\t\t\t\t\tfirstName\n\t\t\t\t\t\tlastName\n\t\t\t\t\t\tgender\n\t\t\t\t\t\tgroup\n\t\t\t\t\t\tmtknr\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": typeof types.CourseStudentsDocument,
"\n\t\t\t\tquery CourseYAML($name: String!) {\n\t\t\t\t\tcourseYAML(name: $name)\n\t\t\t\t}\n\t\t\t": typeof types.CourseYamlDocument,
"\n\t\t\t\tquery ScheduledJobs {\n\t\t\t\t\tscheduledJobs {\n\t\t\t\t\t\tid\n\t\t\t\t\t\top\n\t\t\t\t\t\tcourse\n\t\t\t\t\t\tassignment\n\t\t\t\t\t\trunAt\n\t\t\t\t\t\tgraceMinutes\n\t\t\t\t\t\tstatus\n\t\t\t\t\t\tcreatedAt\n\t\t\t\t\t\tstartedAt\n\t\t\t\t\t\tfinishedAt\n\t\t\t\t\t\terr\n\t\t\t\t\t\tparams {\n\t\t\t\t\t\t\tkey\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": typeof types.ScheduledJobsDocument,
@@ -54,6 +54,7 @@ const documents: Documents = {
"\n\tsubscription CourseCheckProgress($name: String!) {\n\t\tcourseCheckProgress(name: $name) {\n\t\t\tmessage\n\t\t\tdone\n\t\t\terror\n\t\t\tresult {\n\t\t\t\tcourse\n\t\t\t\terrors\n\t\t\t\tok\n\t\t\t\tstudents {\n\t\t\t\t\tinput\n\t\t\t\t\tstatus\n\t\t\t\t\tmessage\n\t\t\t\t}\n\t\t\t\tgroups {\n\t\t\t\t\tname\n\t\t\t\t\tmembers {\n\t\t\t\t\t\tinput\n\t\t\t\t\t\tstatus\n\t\t\t\t\t\tmessage\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tduplicates {\n\t\t\t\t\tstudent\n\t\t\t\t\tgroups\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n": types.CourseCheckProgressDocument,
"\n\tsubscription RunOp($token: String!, $confirmPhrase: String) {\n\t\trunOp(token: $token, confirmPhrase: $confirmPhrase) {\n\t\t\tlevel\n\t\t\ttext\n\t\t}\n\t}\n": types.RunOpDocument,
"\n\tsubscription AssignmentReportProgress($course: String!, $name: String!) {\n\t\tassignmentReportProgress(course: $course, name: $name) {\n\t\t\tmessage\n\t\t\tdone\n\t\t\terror\n\t\t\treport {\n\t\t\t\tcourse\n\t\t\t\tassignment\n\t\t\t\turl\n\t\t\t\tdescription\n\t\t\t\tgenerated\n\t\t\t\thasReleaseMergeRequest\n\t\t\t\thasReleaseDockerImages\n\t\t\t\tprojects {\n\t\t\t\t\tname\n\t\t\t\t\tactive\n\t\t\t\t\temptyRepo\n\t\t\t\t\tcommits\n\t\t\t\t\tlastActivity\n\t\t\t\t\twebUrl\n\t\t\t\t\topenIssuesCount\n\t\t\t\t\topenMergeRequestsCount\n\t\t\t\t\tmembers {\n\t\t\t\t\t\tname\n\t\t\t\t\t\tusername\n\t\t\t\t\t\twebUrl\n\t\t\t\t\t}\n\t\t\t\t\tlastCommit {\n\t\t\t\t\t\ttitle\n\t\t\t\t\t\tcommitterName\n\t\t\t\t\t\tcommittedDate\n\t\t\t\t\t\twebUrl\n\t\t\t\t\t}\n\t\t\t\t\trelease {\n\t\t\t\t\t\tmergeRequest {\n\t\t\t\t\t\t\tfound\n\t\t\t\t\t\t\twebUrl\n\t\t\t\t\t\t\tpipelineStatus\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdockerImages {\n\t\t\t\t\t\t\tstatus\n\t\t\t\t\t\t\timages {\n\t\t\t\t\t\t\t\twanted\n\t\t\t\t\t\t\t\timage\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n": types.AssignmentReportProgressDocument,
+ "\n\tsubscription CourseRepoOverviewProgress($course: String!) {\n\t\tcourseRepoOverviewProgress(course: $course) {\n\t\t\ttotal\n\t\t\tdone\n\t\t\terror\n\t\t\tassignment {\n\t\t\t\tname\n\t\t\t\tper\n\t\t\t\ttargets\n\t\t\t\texisting\n\t\t\t\tnote\n\t\t\t\trepos {\n\t\t\t\t\tfor\n\t\t\t\t\turl\n\t\t\t\t\texists\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n": types.CourseRepoOverviewProgressDocument,
"\n\t\t\t\tquery Me {\n\t\t\t\t\tme {\n\t\t\t\t\t\temail\n\t\t\t\t\t\tname\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": types.MeDocument,
"\n\t\t\t\tquery ServerInfo {\n\t\t\t\t\tserverInfo {\n\t\t\t\t\t\tversion\n\t\t\t\t\t\tcommit\n\t\t\t\t\t\tdate\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": types.ServerInfoDocument,
"\n\t\t\tmutation CopyAssignment($course: String!, $from: String!, $newName: String!) {\n\t\t\t\tcopyAssignment(course: $course, from: $from, newName: $newName) {\n\t\t\t\t\tname\n\t\t\t\t}\n\t\t\t}\n\t\t": types.CopyAssignmentDocument,
@@ -79,7 +80,6 @@ const documents: Documents = {
"\n\t\t\t\tquery CourseLint($name: String!) {\n\t\t\t\t\tcourseLint(name: $name) {\n\t\t\t\t\t\tpath\n\t\t\t\t\t\tmessage\n\t\t\t\t\t\tseverity\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": types.CourseLintDocument,
"\n\t\t\t\tquery CourseActivity($name: String!) {\n\t\t\t\t\tcourseActivity(course: $name) {\n\t\t\t\t\t\tassignment\n\t\t\t\t\t\top\n\t\t\t\t\t\tstatus\n\t\t\t\t\t\tdetail\n\t\t\t\t\t\tat\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": types.CourseActivityDocument,
"\n\t\t\t\tquery AssignmentEditor($course: String!, $name: String!) {\n\t\t\t\t\tcourse(name: $course) {\n\t\t\t\t\t\tassignmentNames\n\t\t\t\t\t}\n\t\t\t\t\tassignmentSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tgroup\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\tdeprecated\n\t\t\t\t\t\texample\n\t\t\t\t\t\toptions {\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t\tlabel\n\t\t\t\t\t\t\tdescription\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbranchRuleSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\texample\n\t\t\t\t\t}\n\t\t\t\t\tapprovalSettingsSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\texample\n\t\t\t\t\t\toptions {\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t\tlabel\n\t\t\t\t\t\t\tdescription\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tapprovalRuleSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\texample\n\t\t\t\t\t}\n\t\t\t\t\tassignment(course: $course, name: $name) {\n\t\t\t\t\t\tcourse\n\t\t\t\t\t\tname\n\t\t\t\t\t\textends\n\t\t\t\t\t\textendsOptions\n\t\t\t\t\t\tabstract\n\t\t\t\t\t\town {\n\t\t\t\t\t\t\tkey\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresolved\n\t\t\t\t\t\tresolveError\n\t\t\t\t\t}\n\t\t\t\t\tassignmentUrls(course: $course, name: $name) {\n\t\t\t\t\t\tper\n\t\t\t\t\t\tgroupUrl\n\t\t\t\t\t\trepos {\n\t\t\t\t\t\t\tfor\n\t\t\t\t\t\t\turl\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tassignmentActivity(course: $course, name: $name) {\n\t\t\t\t\t\top\n\t\t\t\t\t\tstatus\n\t\t\t\t\t\tdetail\n\t\t\t\t\t\tat\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": types.AssignmentEditorDocument,
- "\n\t\t\t\tquery CourseRepoOverview($course: String!) {\n\t\t\t\t\tcourseRepoOverview(course: $course) {\n\t\t\t\t\t\tname\n\t\t\t\t\t\tper\n\t\t\t\t\t\ttargets\n\t\t\t\t\t\texisting\n\t\t\t\t\t\tnote\n\t\t\t\t\t\trepos {\n\t\t\t\t\t\t\tfor\n\t\t\t\t\t\t\turl\n\t\t\t\t\t\t\texists\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": types.CourseRepoOverviewDocument,
"\n\t\t\t\tquery CourseStudents($course: String!) {\n\t\t\t\t\tcourseStudents(course: $course) {\n\t\t\t\t\t\temail\n\t\t\t\t\t\tfound\n\t\t\t\t\t\tfirstName\n\t\t\t\t\t\tlastName\n\t\t\t\t\t\tgender\n\t\t\t\t\t\tgroup\n\t\t\t\t\t\tmtknr\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": types.CourseStudentsDocument,
"\n\t\t\t\tquery CourseYAML($name: String!) {\n\t\t\t\t\tcourseYAML(name: $name)\n\t\t\t\t}\n\t\t\t": types.CourseYamlDocument,
"\n\t\t\t\tquery ScheduledJobs {\n\t\t\t\t\tscheduledJobs {\n\t\t\t\t\t\tid\n\t\t\t\t\t\top\n\t\t\t\t\t\tcourse\n\t\t\t\t\t\tassignment\n\t\t\t\t\t\trunAt\n\t\t\t\t\t\tgraceMinutes\n\t\t\t\t\t\tstatus\n\t\t\t\t\t\tcreatedAt\n\t\t\t\t\t\tstartedAt\n\t\t\t\t\t\tfinishedAt\n\t\t\t\t\t\terr\n\t\t\t\t\t\tparams {\n\t\t\t\t\t\t\tkey\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t": types.ScheduledJobsDocument,
@@ -116,6 +116,10 @@ export function graphql(source: "\n\tsubscription RunOp($token: String!, $confir
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n\tsubscription AssignmentReportProgress($course: String!, $name: String!) {\n\t\tassignmentReportProgress(course: $course, name: $name) {\n\t\t\tmessage\n\t\t\tdone\n\t\t\terror\n\t\t\treport {\n\t\t\t\tcourse\n\t\t\t\tassignment\n\t\t\t\turl\n\t\t\t\tdescription\n\t\t\t\tgenerated\n\t\t\t\thasReleaseMergeRequest\n\t\t\t\thasReleaseDockerImages\n\t\t\t\tprojects {\n\t\t\t\t\tname\n\t\t\t\t\tactive\n\t\t\t\t\temptyRepo\n\t\t\t\t\tcommits\n\t\t\t\t\tlastActivity\n\t\t\t\t\twebUrl\n\t\t\t\t\topenIssuesCount\n\t\t\t\t\topenMergeRequestsCount\n\t\t\t\t\tmembers {\n\t\t\t\t\t\tname\n\t\t\t\t\t\tusername\n\t\t\t\t\t\twebUrl\n\t\t\t\t\t}\n\t\t\t\t\tlastCommit {\n\t\t\t\t\t\ttitle\n\t\t\t\t\t\tcommitterName\n\t\t\t\t\t\tcommittedDate\n\t\t\t\t\t\twebUrl\n\t\t\t\t\t}\n\t\t\t\t\trelease {\n\t\t\t\t\t\tmergeRequest {\n\t\t\t\t\t\t\tfound\n\t\t\t\t\t\t\twebUrl\n\t\t\t\t\t\t\tpipelineStatus\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdockerImages {\n\t\t\t\t\t\t\tstatus\n\t\t\t\t\t\t\timages {\n\t\t\t\t\t\t\t\twanted\n\t\t\t\t\t\t\t\timage\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n"): (typeof documents)["\n\tsubscription AssignmentReportProgress($course: String!, $name: String!) {\n\t\tassignmentReportProgress(course: $course, name: $name) {\n\t\t\tmessage\n\t\t\tdone\n\t\t\terror\n\t\t\treport {\n\t\t\t\tcourse\n\t\t\t\tassignment\n\t\t\t\turl\n\t\t\t\tdescription\n\t\t\t\tgenerated\n\t\t\t\thasReleaseMergeRequest\n\t\t\t\thasReleaseDockerImages\n\t\t\t\tprojects {\n\t\t\t\t\tname\n\t\t\t\t\tactive\n\t\t\t\t\temptyRepo\n\t\t\t\t\tcommits\n\t\t\t\t\tlastActivity\n\t\t\t\t\twebUrl\n\t\t\t\t\topenIssuesCount\n\t\t\t\t\topenMergeRequestsCount\n\t\t\t\t\tmembers {\n\t\t\t\t\t\tname\n\t\t\t\t\t\tusername\n\t\t\t\t\t\twebUrl\n\t\t\t\t\t}\n\t\t\t\t\tlastCommit {\n\t\t\t\t\t\ttitle\n\t\t\t\t\t\tcommitterName\n\t\t\t\t\t\tcommittedDate\n\t\t\t\t\t\twebUrl\n\t\t\t\t\t}\n\t\t\t\t\trelease {\n\t\t\t\t\t\tmergeRequest {\n\t\t\t\t\t\t\tfound\n\t\t\t\t\t\t\twebUrl\n\t\t\t\t\t\t\tpipelineStatus\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdockerImages {\n\t\t\t\t\t\t\tstatus\n\t\t\t\t\t\t\timages {\n\t\t\t\t\t\t\t\twanted\n\t\t\t\t\t\t\t\timage\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n"];
+/**
+ * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
+ */
+export function graphql(source: "\n\tsubscription CourseRepoOverviewProgress($course: String!) {\n\t\tcourseRepoOverviewProgress(course: $course) {\n\t\t\ttotal\n\t\t\tdone\n\t\t\terror\n\t\t\tassignment {\n\t\t\t\tname\n\t\t\t\tper\n\t\t\t\ttargets\n\t\t\t\texisting\n\t\t\t\tnote\n\t\t\t\trepos {\n\t\t\t\t\tfor\n\t\t\t\t\turl\n\t\t\t\t\texists\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n"): (typeof documents)["\n\tsubscription CourseRepoOverviewProgress($course: String!) {\n\t\tcourseRepoOverviewProgress(course: $course) {\n\t\t\ttotal\n\t\t\tdone\n\t\t\terror\n\t\t\tassignment {\n\t\t\t\tname\n\t\t\t\tper\n\t\t\t\ttargets\n\t\t\t\texisting\n\t\t\t\tnote\n\t\t\t\trepos {\n\t\t\t\t\tfor\n\t\t\t\t\turl\n\t\t\t\t\texists\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -216,10 +220,6 @@ export function graphql(source: "\n\t\t\t\tquery CourseActivity($name: String!)
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n\t\t\t\tquery AssignmentEditor($course: String!, $name: String!) {\n\t\t\t\t\tcourse(name: $course) {\n\t\t\t\t\t\tassignmentNames\n\t\t\t\t\t}\n\t\t\t\t\tassignmentSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tgroup\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\tdeprecated\n\t\t\t\t\t\texample\n\t\t\t\t\t\toptions {\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t\tlabel\n\t\t\t\t\t\t\tdescription\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbranchRuleSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\texample\n\t\t\t\t\t}\n\t\t\t\t\tapprovalSettingsSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\texample\n\t\t\t\t\t\toptions {\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t\tlabel\n\t\t\t\t\t\t\tdescription\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tapprovalRuleSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\texample\n\t\t\t\t\t}\n\t\t\t\t\tassignment(course: $course, name: $name) {\n\t\t\t\t\t\tcourse\n\t\t\t\t\t\tname\n\t\t\t\t\t\textends\n\t\t\t\t\t\textendsOptions\n\t\t\t\t\t\tabstract\n\t\t\t\t\t\town {\n\t\t\t\t\t\t\tkey\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresolved\n\t\t\t\t\t\tresolveError\n\t\t\t\t\t}\n\t\t\t\t\tassignmentUrls(course: $course, name: $name) {\n\t\t\t\t\t\tper\n\t\t\t\t\t\tgroupUrl\n\t\t\t\t\t\trepos {\n\t\t\t\t\t\t\tfor\n\t\t\t\t\t\t\turl\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tassignmentActivity(course: $course, name: $name) {\n\t\t\t\t\t\top\n\t\t\t\t\t\tstatus\n\t\t\t\t\t\tdetail\n\t\t\t\t\t\tat\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t"): (typeof documents)["\n\t\t\t\tquery AssignmentEditor($course: String!, $name: String!) {\n\t\t\t\t\tcourse(name: $course) {\n\t\t\t\t\t\tassignmentNames\n\t\t\t\t\t}\n\t\t\t\t\tassignmentSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tgroup\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\tdeprecated\n\t\t\t\t\t\texample\n\t\t\t\t\t\toptions {\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t\tlabel\n\t\t\t\t\t\t\tdescription\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbranchRuleSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\texample\n\t\t\t\t\t}\n\t\t\t\t\tapprovalSettingsSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\texample\n\t\t\t\t\t\toptions {\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t\tlabel\n\t\t\t\t\t\t\tdescription\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tapprovalRuleSchema {\n\t\t\t\t\t\tkey\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\tdescription\n\t\t\t\t\t\tkind\n\t\t\t\t\t\trequired\n\t\t\t\t\t\texample\n\t\t\t\t\t}\n\t\t\t\t\tassignment(course: $course, name: $name) {\n\t\t\t\t\t\tcourse\n\t\t\t\t\t\tname\n\t\t\t\t\t\textends\n\t\t\t\t\t\textendsOptions\n\t\t\t\t\t\tabstract\n\t\t\t\t\t\town {\n\t\t\t\t\t\t\tkey\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresolved\n\t\t\t\t\t\tresolveError\n\t\t\t\t\t}\n\t\t\t\t\tassignmentUrls(course: $course, name: $name) {\n\t\t\t\t\t\tper\n\t\t\t\t\t\tgroupUrl\n\t\t\t\t\t\trepos {\n\t\t\t\t\t\t\tfor\n\t\t\t\t\t\t\turl\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tassignmentActivity(course: $course, name: $name) {\n\t\t\t\t\t\top\n\t\t\t\t\t\tstatus\n\t\t\t\t\t\tdetail\n\t\t\t\t\t\tat\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t"];
-/**
- * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
- */
-export function graphql(source: "\n\t\t\t\tquery CourseRepoOverview($course: String!) {\n\t\t\t\t\tcourseRepoOverview(course: $course) {\n\t\t\t\t\t\tname\n\t\t\t\t\t\tper\n\t\t\t\t\t\ttargets\n\t\t\t\t\t\texisting\n\t\t\t\t\t\tnote\n\t\t\t\t\t\trepos {\n\t\t\t\t\t\t\tfor\n\t\t\t\t\t\t\turl\n\t\t\t\t\t\t\texists\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t"): (typeof documents)["\n\t\t\t\tquery CourseRepoOverview($course: String!) {\n\t\t\t\t\tcourseRepoOverview(course: $course) {\n\t\t\t\t\t\tname\n\t\t\t\t\t\tper\n\t\t\t\t\t\ttargets\n\t\t\t\t\t\texisting\n\t\t\t\t\t\tnote\n\t\t\t\t\t\trepos {\n\t\t\t\t\t\t\tfor\n\t\t\t\t\t\t\turl\n\t\t\t\t\t\t\texists\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
diff --git a/src/lib/gql/graphql.ts b/src/lib/gql/graphql.ts
index 53fa801..c5cc74c 100644
--- a/src/lib/gql/graphql.ts
+++ b/src/lib/gql/graphql.ts
@@ -108,6 +108,13 @@ export type AssignmentReportProgressSubscriptionVariables = Exact<{
export type AssignmentReportProgressSubscription = { assignmentReportProgress: { message: string, done: boolean, error: string | null, report: { course: string, assignment: string, url: string, description: string, generated: string | null, hasReleaseMergeRequest: boolean, hasReleaseDockerImages: boolean, projects: Array<{ name: string, active: boolean, emptyRepo: boolean, commits: number, lastActivity: string | null, webUrl: string, openIssuesCount: number, openMergeRequestsCount: number, members: Array<{ name: string, username: string, webUrl: string }>, lastCommit: { title: string, committerName: string, committedDate: string | null, webUrl: string } | null, release: { mergeRequest: { found: boolean, webUrl: string, pipelineStatus: string } | null, dockerImages: { status: string, images: Array<{ wanted: string, image: string | null }> } | null } | null }> } | null } };
+export type CourseRepoOverviewProgressSubscriptionVariables = Exact<{
+ course: string;
+}>;
+
+
+export type CourseRepoOverviewProgressSubscription = { courseRepoOverviewProgress: { total: number, done: boolean, error: string | null, assignment: { name: string, per: string, targets: number, existing: number, note: string | null, repos: Array<{ for: string, url: string, exists: boolean }> } | null } };
+
export type MeQueryVariables = Exact<{ [key: string]: never; }>;
@@ -304,13 +311,6 @@ export type AssignmentEditorQueryVariables = Exact<{
export type AssignmentEditorQuery = { course: { assignmentNames: Array } | null, assignmentSchema: Array<{ key: string, label: string, description: string, group: string, kind: FieldKind, required: boolean, deprecated: boolean, example: string | null, options: Array<{ value: string, label: string, description: string }> }>, branchRuleSchema: Array<{ key: string, label: string, description: string, kind: FieldKind, required: boolean, example: string | null }>, approvalSettingsSchema: Array<{ key: string, label: string, description: string, kind: FieldKind, required: boolean, example: string | null, options: Array<{ value: string, label: string, description: string }> }>, approvalRuleSchema: Array<{ key: string, label: string, description: string, kind: FieldKind, required: boolean, example: string | null }>, assignment: { course: string, name: string, extends: string | null, extendsOptions: Array, abstract: boolean, resolved: string, resolveError: string | null, own: Array<{ key: string, value: string }> } | null, assignmentUrls: { per: string, groupUrl: string, repos: Array<{ for: string, url: string }> } | null, assignmentActivity: Array<{ op: string, status: string, detail: string, at: string }> };
-export type CourseRepoOverviewQueryVariables = Exact<{
- course: string;
-}>;
-
-
-export type CourseRepoOverviewQuery = { courseRepoOverview: Array<{ name: string, per: string, targets: number, existing: number, note: string | null, repos: Array<{ for: string, url: string, exists: boolean }> }> };
-
export type CourseStudentsQueryVariables = Exact<{
course: string;
}>;
@@ -340,6 +340,7 @@ export const AuthCheckDocument = {"kind":"Document","definitions":[{"kind":"Oper
export const CourseCheckProgressDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"CourseCheckProgress"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"courseCheckProgress"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"done"}},{"kind":"Field","name":{"kind":"Name","value":"error"}},{"kind":"Field","name":{"kind":"Name","value":"result"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course"}},{"kind":"Field","name":{"kind":"Name","value":"errors"}},{"kind":"Field","name":{"kind":"Name","value":"ok"}},{"kind":"Field","name":{"kind":"Name","value":"students"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"input"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}},{"kind":"Field","name":{"kind":"Name","value":"groups"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"members"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"input"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"duplicates"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"student"}},{"kind":"Field","name":{"kind":"Name","value":"groups"}}]}}]}}]}}]}}]} as unknown as DocumentNode;
export const RunOpDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"RunOp"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"token"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"confirmPhrase"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"runOp"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"token"},"value":{"kind":"Variable","name":{"kind":"Name","value":"token"}}},{"kind":"Argument","name":{"kind":"Name","value":"confirmPhrase"},"value":{"kind":"Variable","name":{"kind":"Name","value":"confirmPhrase"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"level"}},{"kind":"Field","name":{"kind":"Name","value":"text"}}]}}]}}]} as unknown as DocumentNode;
export const AssignmentReportProgressDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"AssignmentReportProgress"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"course"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignmentReportProgress"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course"},"value":{"kind":"Variable","name":{"kind":"Name","value":"course"}}},{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"done"}},{"kind":"Field","name":{"kind":"Name","value":"error"}},{"kind":"Field","name":{"kind":"Name","value":"report"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course"}},{"kind":"Field","name":{"kind":"Name","value":"assignment"}},{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"generated"}},{"kind":"Field","name":{"kind":"Name","value":"hasReleaseMergeRequest"}},{"kind":"Field","name":{"kind":"Name","value":"hasReleaseDockerImages"}},{"kind":"Field","name":{"kind":"Name","value":"projects"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"emptyRepo"}},{"kind":"Field","name":{"kind":"Name","value":"commits"}},{"kind":"Field","name":{"kind":"Name","value":"lastActivity"}},{"kind":"Field","name":{"kind":"Name","value":"webUrl"}},{"kind":"Field","name":{"kind":"Name","value":"openIssuesCount"}},{"kind":"Field","name":{"kind":"Name","value":"openMergeRequestsCount"}},{"kind":"Field","name":{"kind":"Name","value":"members"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"webUrl"}}]}},{"kind":"Field","name":{"kind":"Name","value":"lastCommit"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"committerName"}},{"kind":"Field","name":{"kind":"Name","value":"committedDate"}},{"kind":"Field","name":{"kind":"Name","value":"webUrl"}}]}},{"kind":"Field","name":{"kind":"Name","value":"release"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"mergeRequest"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"found"}},{"kind":"Field","name":{"kind":"Name","value":"webUrl"}},{"kind":"Field","name":{"kind":"Name","value":"pipelineStatus"}}]}},{"kind":"Field","name":{"kind":"Name","value":"dockerImages"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"images"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"wanted"}},{"kind":"Field","name":{"kind":"Name","value":"image"}}]}}]}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode;
+export const CourseRepoOverviewProgressDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"CourseRepoOverviewProgress"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"course"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"courseRepoOverviewProgress"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course"},"value":{"kind":"Variable","name":{"kind":"Name","value":"course"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total"}},{"kind":"Field","name":{"kind":"Name","value":"done"}},{"kind":"Field","name":{"kind":"Name","value":"error"}},{"kind":"Field","name":{"kind":"Name","value":"assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"per"}},{"kind":"Field","name":{"kind":"Name","value":"targets"}},{"kind":"Field","name":{"kind":"Name","value":"existing"}},{"kind":"Field","name":{"kind":"Name","value":"note"}},{"kind":"Field","name":{"kind":"Name","value":"repos"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"for"}},{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"exists"}}]}}]}}]}}]}}]} as unknown as DocumentNode;
export const MeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Me"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"me"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode;
export const ServerInfoDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ServerInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serverInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"commit"}},{"kind":"Field","name":{"kind":"Name","value":"date"}}]}}]}}]} as unknown as DocumentNode;
export const CopyAssignmentDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CopyAssignment"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"course"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"from"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"newName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"copyAssignment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course"},"value":{"kind":"Variable","name":{"kind":"Name","value":"course"}}},{"kind":"Argument","name":{"kind":"Name","value":"from"},"value":{"kind":"Variable","name":{"kind":"Name","value":"from"}}},{"kind":"Argument","name":{"kind":"Name","value":"newName"},"value":{"kind":"Variable","name":{"kind":"Name","value":"newName"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode;
@@ -365,7 +366,6 @@ export const CourseDocument = {"kind":"Document","definitions":[{"kind":"Operati
export const CourseLintDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CourseLint"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"courseLint"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"path"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"severity"}}]}}]}}]} as unknown as DocumentNode;
export const CourseActivityDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CourseActivity"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"courseActivity"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment"}},{"kind":"Field","name":{"kind":"Name","value":"op"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"detail"}},{"kind":"Field","name":{"kind":"Name","value":"at"}}]}}]}}]} as unknown as DocumentNode;
export const AssignmentEditorDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AssignmentEditor"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"course"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"course"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignmentNames"}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignmentSchema"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"group"}},{"kind":"Field","name":{"kind":"Name","value":"kind"}},{"kind":"Field","name":{"kind":"Name","value":"required"}},{"kind":"Field","name":{"kind":"Name","value":"deprecated"}},{"kind":"Field","name":{"kind":"Name","value":"example"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"branchRuleSchema"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"kind"}},{"kind":"Field","name":{"kind":"Name","value":"required"}},{"kind":"Field","name":{"kind":"Name","value":"example"}}]}},{"kind":"Field","name":{"kind":"Name","value":"approvalSettingsSchema"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"kind"}},{"kind":"Field","name":{"kind":"Name","value":"required"}},{"kind":"Field","name":{"kind":"Name","value":"example"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"approvalRuleSchema"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"kind"}},{"kind":"Field","name":{"kind":"Name","value":"required"}},{"kind":"Field","name":{"kind":"Name","value":"example"}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course"},"value":{"kind":"Variable","name":{"kind":"Name","value":"course"}}},{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"extends"}},{"kind":"Field","name":{"kind":"Name","value":"extendsOptions"}},{"kind":"Field","name":{"kind":"Name","value":"abstract"}},{"kind":"Field","name":{"kind":"Name","value":"own"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}},{"kind":"Field","name":{"kind":"Name","value":"resolved"}},{"kind":"Field","name":{"kind":"Name","value":"resolveError"}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignmentUrls"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course"},"value":{"kind":"Variable","name":{"kind":"Name","value":"course"}}},{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"per"}},{"kind":"Field","name":{"kind":"Name","value":"groupUrl"}},{"kind":"Field","name":{"kind":"Name","value":"repos"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"for"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignmentActivity"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course"},"value":{"kind":"Variable","name":{"kind":"Name","value":"course"}}},{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"op"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"detail"}},{"kind":"Field","name":{"kind":"Name","value":"at"}}]}}]}}]} as unknown as DocumentNode;
-export const CourseRepoOverviewDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CourseRepoOverview"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"course"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"courseRepoOverview"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course"},"value":{"kind":"Variable","name":{"kind":"Name","value":"course"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"per"}},{"kind":"Field","name":{"kind":"Name","value":"targets"}},{"kind":"Field","name":{"kind":"Name","value":"existing"}},{"kind":"Field","name":{"kind":"Name","value":"note"}},{"kind":"Field","name":{"kind":"Name","value":"repos"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"for"}},{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"exists"}}]}}]}}]}}]} as unknown as DocumentNode;
export const CourseStudentsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CourseStudents"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"course"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"courseStudents"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course"},"value":{"kind":"Variable","name":{"kind":"Name","value":"course"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"found"}},{"kind":"Field","name":{"kind":"Name","value":"firstName"}},{"kind":"Field","name":{"kind":"Name","value":"lastName"}},{"kind":"Field","name":{"kind":"Name","value":"gender"}},{"kind":"Field","name":{"kind":"Name","value":"group"}},{"kind":"Field","name":{"kind":"Name","value":"mtknr"}}]}}]}}]} as unknown as DocumentNode;
export const CourseYamlDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CourseYAML"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"courseYAML"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}}]}]}}]} as unknown as DocumentNode;
export const ScheduledJobsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ScheduledJobs"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"scheduledJobs"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"op"}},{"kind":"Field","name":{"kind":"Name","value":"course"}},{"kind":"Field","name":{"kind":"Name","value":"assignment"}},{"kind":"Field","name":{"kind":"Name","value":"runAt"}},{"kind":"Field","name":{"kind":"Name","value":"graceMinutes"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"startedAt"}},{"kind":"Field","name":{"kind":"Name","value":"finishedAt"}},{"kind":"Field","name":{"kind":"Name","value":"err"}},{"kind":"Field","name":{"kind":"Name","value":"params"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]}}]} as unknown as DocumentNode;
diff --git a/src/lib/reposSubscription.ts b/src/lib/reposSubscription.ts
new file mode 100644
index 0000000..2efe4d1
--- /dev/null
+++ b/src/lib/reposSubscription.ts
@@ -0,0 +1,50 @@
+import { graphql } from '$lib/gql';
+import { subscribe } from '$lib/wsClient';
+import type { CourseRepoOverviewProgressSubscription } from '$lib/gql/graphql';
+
+// One progress event of the repo-overview stream (the subscription payload).
+export type RepoOverviewEvent =
+ CourseRepoOverviewProgressSubscription['courseRepoOverviewProgress'];
+
+const DOC = graphql(`
+ subscription CourseRepoOverviewProgress($course: String!) {
+ courseRepoOverviewProgress(course: $course) {
+ total
+ done
+ error
+ assignment {
+ name
+ per
+ targets
+ existing
+ note
+ repos {
+ for
+ url
+ exists
+ }
+ }
+ }
+ }
+`);
+
+/**
+ * Subscribe to the live repo-overview stream. Calls `next` for every event
+ * (one finished assignment, then a final done) and `error` on a transport failure.
+ * Returns a cleanup function.
+ */
+export function subscribeRepoOverview(
+ course: string,
+ handlers: { next: (e: RepoOverviewEvent) => void; error: (message: string) => void }
+): () => void {
+ return subscribe(
+ DOC,
+ { course },
+ {
+ next: (d) => {
+ if (d.courseRepoOverviewProgress) handlers.next(d.courseRepoOverviewProgress);
+ },
+ error: handlers.error
+ }
+ );
+}
diff --git a/src/routes/courses/[name]/repos/+page.server.ts b/src/routes/courses/[name]/repos/+page.server.ts
index b8e8635..84a28d2 100644
--- a/src/routes/courses/[name]/repos/+page.server.ts
+++ b/src/routes/courses/[name]/repos/+page.server.ts
@@ -1,38 +1,10 @@
-import { graphql } from '$lib/gql';
-import { backendRequest } from '$lib/server/backend';
-import { gqlErrorMessage } from '$lib/gqlError';
import type { PageServerLoad } from './$types';
/**
- * Übersicht der tatsächlich generierten Repos pro Assignment. Fragt GitLab
- * serverseitig ab (ein Gruppen-Listing pro Assignment) — kann ein paar Sekunden
- * dauern und braucht einen hinterlegten GitLab-Token; ein Fehler (z. B. kein Token)
- * wird als `error` durchgereicht statt die Seite scheitern zu lassen.
+ * Die Repo-Übersicht wird live im Browser über eine WebSocket-Subscription geladen
+ * (assignmentweise, mit Fortschritt), nicht im SSR — so blockiert die Seite nicht,
+ * während GitLab abgefragt wird. Der Load reicht nur die Route-Parameter durch.
*/
export const load: PageServerLoad = async ({ params }) => {
- const course = params.name;
- try {
- const d = await backendRequest(
- graphql(`
- query CourseRepoOverview($course: String!) {
- courseRepoOverview(course: $course) {
- name
- per
- targets
- existing
- note
- repos {
- for
- url
- exists
- }
- }
- }
- `),
- { course }
- );
- return { course, overview: d?.courseRepoOverview ?? [], error: null as string | null };
- } catch (e) {
- return { course, overview: null, error: gqlErrorMessage(e) };
- }
+ return { course: params.name };
};
diff --git a/src/routes/courses/[name]/repos/+page.svelte b/src/routes/courses/[name]/repos/+page.svelte
index 1e58dad..d90525f 100644
--- a/src/routes/courses/[name]/repos/+page.svelte
+++ b/src/routes/courses/[name]/repos/+page.svelte
@@ -1,13 +1,50 @@
@@ -25,8 +62,21 @@
(GitLab-Token nötig).
+
+ {#if !done}
+
+ prüfe GitLab … {checked}{total ? `/${total}` : ''} Assignments
+ {:else if !error}
+ ✓ fertig ({checked} Assignments)
+ {/if}
+
+
+ {#if total > 0 && !done}
+
+ {/if}
+
{#if error}
-
+
{error}
{#if needsToken}
@@ -34,11 +84,11 @@
GitLab-Token hinterlegen →
{/if}
- {:else if overview.length === 0}
-
Keine Assignments in diesem Kurs.
- {:else}
+ {/if}
+
+ {#if sorted.length > 0}
- {#each overview as a (a.name)}
+ {#each sorted as a (a.name)}
{@const miss = missing(a)}
@@ -49,7 +99,7 @@
{a.name}
{#if a.note}
- —
+ —
{a.note}
{:else}